summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.expeditor/config.yml14
-rw-r--r--.github/CODEOWNERS2
-rw-r--r--.github/ISSUE_TEMPLATE.md47
-rw-r--r--.gitignore4
-rw-r--r--.mailmap4
-rw-r--r--.travis.yml217
-rw-r--r--CHANGELOG.md213
-rw-r--r--Dockerfile4
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock171
-rw-r--r--RELEASE_NOTES.md161
-rw-r--r--VERSION2
-rw-r--r--acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml11
-rw-r--r--acceptance/.shared/kitchen_acceptance/.kitchen.vagrant.yml2
-rw-r--r--acceptance/Gemfile4
-rw-r--r--acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb7
-rw-r--r--acceptance/top-cookbooks/.kitchen.docker.yml13
-rw-r--r--acceptance/top-cookbooks/.kitchen.git.yml11
-rw-r--r--appveyor.yml27
-rwxr-xr-xbin/chef-shell2
-rw-r--r--chef-config/.travis.yml31
-rw-r--r--chef-config/chef-config.gemspec1
-rw-r--r--chef-config/lib/chef-config/config.rb23
-rw-r--r--chef-config/lib/chef-config/mixin/credentials.rb57
-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/lib/chef-config/workstation_config_loader.rb44
-rw-r--r--chef-config/spec/unit/workstation_config_loader_spec.rb144
-rw-r--r--chef.gemspec2
-rwxr-xr-xci/verify-chef.sh2
-rw-r--r--distro/common/html/knife_search.html14
-rw-r--r--distro/common/man/man1/knife-search.112
-rw-r--r--distro/common/markdown/man1/knife-search.mkd4
-rw-r--r--distro/powershell/chef/chef.psm131
-rw-r--r--kitchen-tests/.kitchen.travis.yml24
-rw-r--r--kitchen-tests/.kitchen.yml13
-rw-r--r--kitchen-tests/Berksfile.lock53
-rw-r--r--kitchen-tests/Gemfile17
-rw-r--r--kitchen-tests/Gemfile.lock269
-rw-r--r--kitchen-tests/cookbooks/audit_test/.gitignore15
-rw-r--r--kitchen-tests/cookbooks/audit_test/chefignore95
-rw-r--r--kitchen-tests/cookbooks/base/attributes/default.rb4
-rw-r--r--kitchen-tests/cookbooks/base/metadata.rb4
-rw-r--r--kitchen-tests/cookbooks/base/recipes/default.rb35
-rw-r--r--kitchen-tests/cookbooks/base/recipes/packages.rb2
-rw-r--r--lib/chef/api_client.rb10
-rw-r--r--lib/chef/api_client_v1.rb13
-rw-r--r--lib/chef/application.rb5
-rw-r--r--lib/chef/application/client.rb2
-rw-r--r--lib/chef/application/knife.rb4
-rw-r--r--lib/chef/application/solo.rb9
-rw-r--r--lib/chef/audit/audit_reporter.rb6
-rw-r--r--lib/chef/audit/runner.rb4
-rw-r--r--lib/chef/chef_class.rb4
-rw-r--r--lib/chef/chef_fs/config.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/acl_data_handler.rb2
-rw-r--r--lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb5
-rw-r--r--lib/chef/chef_fs/data_handler/data_handler_base.rb6
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/cookbook_dir.rb4
-rw-r--r--lib/chef/chef_fs/file_system/chef_server/policies_dir.rb4
-rw-r--r--lib/chef/client.rb25
-rw-r--r--lib/chef/cookbook/chefignore.rb4
-rw-r--r--lib/chef/cookbook/cookbook_collection.rb8
-rw-r--r--lib/chef/cookbook/cookbook_version_loader.rb1
-rw-r--r--lib/chef/cookbook/gem_installer.rb4
-rw-r--r--lib/chef/cookbook/metadata.rb7
-rw-r--r--lib/chef/cookbook/synchronizer.rb6
-rw-r--r--lib/chef/cookbook_loader.rb12
-rw-r--r--lib/chef/cookbook_uploader.rb1
-rw-r--r--lib/chef/cookbook_version.rb8
-rw-r--r--lib/chef/data_bag.rb8
-rw-r--r--lib/chef/data_bag_item.rb8
-rw-r--r--lib/chef/data_collector/messages.rb4
-rw-r--r--lib/chef/data_collector/messages/helpers.rb2
-rw-r--r--lib/chef/deprecated.rb20
-rw-r--r--lib/chef/dsl/data_query.rb6
-rw-r--r--lib/chef/dsl/include_attribute.rb6
-rw-r--r--lib/chef/dsl/include_recipe.rb6
-rw-r--r--lib/chef/dsl/platform_introspection.rb6
-rw-r--r--lib/chef/dsl/recipe.rb14
-rw-r--r--lib/chef/environment.rb6
-rw-r--r--lib/chef/event_dispatch/base.rb4
-rw-r--r--lib/chef/guard_interpreter/resource_guard_interpreter.rb4
-rw-r--r--lib/chef/handler.rb4
-rw-r--r--lib/chef/handler/json_file.rb3
-rw-r--r--lib/chef/http.rb22
-rw-r--r--lib/chef/http/basic_client.rb3
-rw-r--r--lib/chef/http/http_request.rb4
-rw-r--r--lib/chef/http/socketless_chef_zero_client.rb4
-rw-r--r--lib/chef/knife.rb33
-rw-r--r--lib/chef/knife/bootstrap.rb2
-rw-r--r--lib/chef/knife/client_delete.rb2
-rw-r--r--lib/chef/knife/configure.rb48
-rw-r--r--lib/chef/knife/cookbook_metadata.rb4
-rw-r--r--lib/chef/knife/cookbook_site_install.rb4
-rw-r--r--lib/chef/knife/cookbook_test.rb4
-rw-r--r--lib/chef/knife/cookbook_upload.rb12
-rw-r--r--lib/chef/knife/core/bootstrap_context.rb2
-rw-r--r--lib/chef/knife/core/status_presenter.rb35
-rw-r--r--lib/chef/knife/core/ui.rb2
-rw-r--r--lib/chef/knife/data_bag_secret_options.rb2
-rw-r--r--lib/chef/knife/data_bag_show.rb2
-rw-r--r--lib/chef/knife/edit.rb2
-rw-r--r--lib/chef/knife/environment_compare.rb6
-rw-r--r--lib/chef/knife/index_rebuild.rb133
-rw-r--r--lib/chef/knife/node_delete.rb2
-rw-r--r--lib/chef/knife/node_policy_set.rb79
-rw-r--r--lib/chef/knife/node_run_list_add.rb2
-rw-r--r--lib/chef/knife/node_run_list_remove.rb2
-rw-r--r--lib/chef/knife/role_env_run_list_add.rb2
-rw-r--r--lib/chef/knife/role_run_list_add.rb2
-rw-r--r--lib/chef/knife/search.rb6
-rw-r--r--lib/chef/knife/ssh.rb109
-rw-r--r--lib/chef/knife/user_create.rb2
-rw-r--r--lib/chef/knife/user_delete.rb2
-rw-r--r--lib/chef/knife/user_edit.rb2
-rw-r--r--lib/chef/knife/user_reregister.rb2
-rw-r--r--lib/chef/knife/user_show.rb2
-rw-r--r--lib/chef/knife/xargs.rb2
-rw-r--r--lib/chef/mixin/api_version_request_handling.rb6
-rw-r--r--lib/chef/mixin/deprecation.rb28
-rw-r--r--lib/chef/mixin/homebrew_user.rb1
-rw-r--r--lib/chef/mixin/language.rb48
-rw-r--r--lib/chef/mixin/language_include_attribute.rb34
-rw-r--r--lib/chef/mixin/language_include_recipe.rb31
-rw-r--r--lib/chef/mixin/openssl_helper.rb119
-rw-r--r--lib/chef/mixin/params_validate.rb28
-rw-r--r--lib/chef/mixin/powershell_out.rb2
-rw-r--r--lib/chef/mixin/properties.rb13
-rw-r--r--lib/chef/mixin/provides.rb5
-rw-r--r--lib/chef/mixin/recipe_definition_dsl_core.rb35
-rw-r--r--lib/chef/mixin/securable.rb6
-rw-r--r--lib/chef/mixin/shell_out.rb4
-rw-r--r--lib/chef/mixin/template.rb4
-rw-r--r--lib/chef/mixin/user_context.rb11
-rw-r--r--lib/chef/mixin/why_run.rb17
-rw-r--r--lib/chef/node.rb12
-rw-r--r--lib/chef/node/attribute.rb123
-rw-r--r--lib/chef/node/attribute_collections.rb16
-rw-r--r--lib/chef/node/common_api.rb2
-rw-r--r--lib/chef/node/immutable_collections.rb203
-rw-r--r--lib/chef/node/mixin/immutablize_array.rb113
-rw-r--r--lib/chef/node/mixin/immutablize_hash.rb116
-rw-r--r--lib/chef/node/mixin/state_tracking.rb12
-rw-r--r--lib/chef/node_map.rb122
-rw-r--r--lib/chef/platform/rebooter.rb10
-rw-r--r--lib/chef/property.rb38
-rw-r--r--lib/chef/provider.rb31
-rw-r--r--lib/chef/provider/apt_preference.rb2
-rw-r--r--lib/chef/provider/apt_repository.rb2
-rw-r--r--lib/chef/provider/apt_update.rb2
-rw-r--r--lib/chef/provider/deploy.rb470
-rw-r--r--lib/chef/provider/deploy/revision.rb107
-rw-r--r--lib/chef/provider/deploy/timestamped.rb34
-rw-r--r--lib/chef/provider/dsc_script.rb6
-rw-r--r--lib/chef/provider/erl_call.rb76
-rw-r--r--lib/chef/provider/file.rb2
-rw-r--r--lib/chef/provider/group/dscl.rb8
-rw-r--r--lib/chef/provider/ifconfig.rb130
-rw-r--r--lib/chef/provider/launchd.rb1
-rw-r--r--lib/chef/provider/log.rb16
-rw-r--r--lib/chef/provider/mount/mount.rb7
-rw-r--r--lib/chef/provider/package.rb46
-rw-r--r--lib/chef/provider/package/apt.rb42
-rw-r--r--lib/chef/provider/package/chocolatey.rb32
-rw-r--r--lib/chef/provider/package/dnf.rb21
-rw-r--r--lib/chef/provider/package/dnf/dnf_helper.py10
-rw-r--r--lib/chef/provider/package/dnf/python_helper.rb15
-rw-r--r--lib/chef/provider/package/dpkg.rb16
-rw-r--r--lib/chef/provider/package/powershell.rb12
-rw-r--r--lib/chef/provider/package/rpm.rb5
-rw-r--r--lib/chef/provider/package/smartos.rb4
-rw-r--r--lib/chef/provider/package/windows.rb15
-rw-r--r--lib/chef/provider/package/yum.rb34
-rw-r--r--lib/chef/provider/package/zypper.rb16
-rw-r--r--lib/chef/provider/reboot.rb12
-rw-r--r--lib/chef/provider/remote_directory.rb6
-rw-r--r--lib/chef/provider/remote_file/http.rb5
-rw-r--r--lib/chef/provider/remote_file/network_file.rb2
-rw-r--r--lib/chef/provider/route.rb4
-rw-r--r--lib/chef/provider/service/debian.rb4
-rw-r--r--lib/chef/provider/service/solaris.rb8
-rw-r--r--lib/chef/provider/service/systemd.rb2
-rw-r--r--lib/chef/provider/service/windows.rb268
-rw-r--r--lib/chef/provider/support/yum_repo.erb6
-rw-r--r--lib/chef/provider/systemd_unit.rb90
-rw-r--r--lib/chef/provider/user/dscl.rb2
-rw-r--r--lib/chef/provider/windows_path.rb13
-rw-r--r--lib/chef/provider/windows_task.rb161
-rw-r--r--lib/chef/provider/yum_repository.rb33
-rw-r--r--lib/chef/provider/zypper_repository.rb112
-rw-r--r--lib/chef/providers.rb5
-rw-r--r--lib/chef/resource.rb34
-rw-r--r--lib/chef/resource/action_class.rb4
-rw-r--r--lib/chef/resource/apt_package.rb2
-rw-r--r--lib/chef/resource/apt_preference.rb4
-rw-r--r--lib/chef/resource/apt_repository.rb14
-rw-r--r--lib/chef/resource/apt_update.rb3
-rw-r--r--lib/chef/resource/bash.rb4
-rw-r--r--lib/chef/resource/batch.rb5
-rw-r--r--lib/chef/resource/bff_package.rb4
-rw-r--r--lib/chef/resource/breakpoint.rb6
-rw-r--r--lib/chef/resource/cab_package.rb12
-rw-r--r--lib/chef/resource/chef_gem.rb13
-rw-r--r--lib/chef/resource/chocolatey_package.rb10
-rw-r--r--lib/chef/resource/cookbook_file.rb28
-rw-r--r--lib/chef/resource/cron.rb2
-rw-r--r--lib/chef/resource/csh.rb4
-rw-r--r--lib/chef/resource/deploy.rb443
-rw-r--r--lib/chef/resource/deploy_revision.rb31
-rw-r--r--lib/chef/resource/directory.rb34
-rw-r--r--lib/chef/resource/dnf_package.rb16
-rw-r--r--lib/chef/resource/dpkg_package.rb2
-rw-r--r--lib/chef/resource/dsc_resource.rb5
-rw-r--r--lib/chef/resource/dsc_script.rb6
-rw-r--r--lib/chef/resource/env.rb3
-rw-r--r--lib/chef/resource/erl_call.rb85
-rw-r--r--lib/chef/resource/execute.rb6
-rw-r--r--lib/chef/resource/file.rb5
-rw-r--r--lib/chef/resource/file/verification.rb10
-rw-r--r--lib/chef/resource/freebsd_package.rb12
-rw-r--r--lib/chef/resource/gem_package.rb2
-rw-r--r--lib/chef/resource/git.rb2
-rw-r--r--lib/chef/resource/group.rb1
-rw-r--r--lib/chef/resource/homebrew_package.rb3
-rw-r--r--lib/chef/resource/http_request.rb2
-rw-r--r--lib/chef/resource/ifconfig.rb173
-rw-r--r--lib/chef/resource/ips_package.rb1
-rw-r--r--lib/chef/resource/ksh.rb6
-rw-r--r--lib/chef/resource/launchd.rb9
-rw-r--r--lib/chef/resource/link.rb13
-rw-r--r--lib/chef/resource/log.rb65
-rw-r--r--lib/chef/resource/lwrp_base.rb5
-rw-r--r--lib/chef/resource/macports_package.rb1
-rw-r--r--lib/chef/resource/mdadm.rb4
-rw-r--r--lib/chef/resource/mount.rb11
-rw-r--r--lib/chef/resource/msu_package.rb15
-rw-r--r--lib/chef/resource/ohai.rb2
-rw-r--r--lib/chef/resource/openbsd_package.rb3
-rw-r--r--lib/chef/resource/openssl_dhparam.rb59
-rw-r--r--lib/chef/resource/openssl_rsa_private_key.rb69
-rw-r--r--lib/chef/resource/openssl_rsa_public_key.rb56
-rw-r--r--lib/chef/resource/osx_profile.rb50
-rw-r--r--lib/chef/resource/package.rb6
-rw-r--r--lib/chef/resource/pacman_package.rb1
-rw-r--r--lib/chef/resource/paludis_package.rb3
-rw-r--r--lib/chef/resource/perl.rb4
-rw-r--r--lib/chef/resource/portage_package.rb1
-rw-r--r--lib/chef/resource/powershell_package.rb5
-rw-r--r--lib/chef/resource/powershell_script.rb8
-rw-r--r--lib/chef/resource/python.rb4
-rw-r--r--lib/chef/resource/reboot.rb34
-rw-r--r--lib/chef/resource/registry_key.rb1
-rw-r--r--lib/chef/resource/remote_directory.rb3
-rw-r--r--lib/chef/resource/remote_file.rb4
-rw-r--r--lib/chef/resource/resource_notification.rb19
-rw-r--r--lib/chef/resource/route.rb1
-rw-r--r--lib/chef/resource/rpm_package.rb1
-rw-r--r--lib/chef/resource/ruby.rb4
-rw-r--r--lib/chef/resource/ruby_block.rb3
-rw-r--r--lib/chef/resource/script.rb4
-rw-r--r--lib/chef/resource/service.rb1
-rw-r--r--lib/chef/resource/smartos_package.rb1
-rw-r--r--lib/chef/resource/solaris_package.rb1
-rw-r--r--lib/chef/resource/subversion.rb1
-rw-r--r--lib/chef/resource/systemd_unit.rb11
-rw-r--r--lib/chef/resource/template.rb9
-rw-r--r--lib/chef/resource/timestamped_deploy.rb26
-rw-r--r--lib/chef/resource/user.rb1
-rw-r--r--lib/chef/resource/windows_package.rb2
-rw-r--r--lib/chef/resource/windows_path.rb15
-rw-r--r--lib/chef/resource/windows_service.rb112
-rw-r--r--lib/chef/resource/windows_task.rb162
-rw-r--r--lib/chef/resource/yum_repository.rb53
-rw-r--r--lib/chef/resource/zypper_package.rb3
-rw-r--r--lib/chef/resource/zypper_repository.rb8
-rw-r--r--lib/chef/resource_reporter.rb3
-rw-r--r--lib/chef/resources.rb7
-rw-r--r--lib/chef/role.rb4
-rw-r--r--lib/chef/run_context.rb10
-rw-r--r--lib/chef/search/query.rb3
-rw-r--r--lib/chef/server_api.rb1
-rw-r--r--lib/chef/shell.rb1
-rw-r--r--lib/chef/shell/model_wrapper.rb2
-rw-r--r--lib/chef/shell/shell_session.rb5
-rw-r--r--lib/chef/util/dsc/lcm_output_parser.rb59
-rw-r--r--lib/chef/util/dsc/local_configuration_manager.rb32
-rw-r--r--lib/chef/util/selinux.rb9
-rw-r--r--lib/chef/util/windows/logon_session.rb7
-rw-r--r--lib/chef/util/windows/volume.rb4
-rw-r--r--lib/chef/version.rb2
-rw-r--r--lib/chef/version/platform.rb18
-rw-r--r--lib/chef/version_constraint/platform.rb2
-rw-r--r--lib/chef/win32/api/security.rb11
-rw-r--r--lib/chef/win32/registry.rb4
-rw-r--r--lib/chef/win32/security.rb30
-rw-r--r--lib/chef/win32_service_constants.rb143
-rw-r--r--omnibus/.kitchen.yml27
-rw-r--r--omnibus/Gemfile1
-rw-r--r--omnibus/Gemfile.lock106
-rw-r--r--omnibus/resources/chef/msi/source.wxs.erb7
-rw-r--r--omnibus_overrides.rb16
-rw-r--r--spec/data/client.d_00/02-strings.rb2
-rwxr-xr-xspec/functional/assets/chefinittest10
-rw-r--r--spec/functional/http/simple_spec.rb16
-rw-r--r--spec/functional/knife/ssh_spec.rb61
-rw-r--r--spec/functional/mixin/powershell_out_spec.rb26
-rw-r--r--spec/functional/rebooter_spec.rb33
-rw-r--r--spec/functional/resource/apt_package_spec.rb (renamed from spec/functional/resource/package_spec.rb)6
-rw-r--r--spec/functional/resource/bff_spec.rb6
-rw-r--r--spec/functional/resource/deploy_revision_spec.rb881
-rw-r--r--spec/functional/resource/ifconfig_spec.rb2
-rw-r--r--spec/functional/resource/mount_spec.rb10
-rw-r--r--spec/functional/resource/registry_spec.rb6
-rw-r--r--spec/functional/resource/remote_file_spec.rb30
-rw-r--r--spec/functional/resource/user/useradd_spec.rb8
-rw-r--r--spec/functional/resource/windows_task_spec.rb349
-rw-r--r--spec/functional/win32/security_spec.rb67
-rw-r--r--spec/integration/knife/data_bag_show_spec.rb2
-rw-r--r--spec/integration/knife/deps_spec.rb4
-rw-r--r--spec/integration/recipes/noop_resource_spec.rb2
-rw-r--r--spec/integration/recipes/recipe_dsl_spec.rb112
-rw-r--r--spec/integration/recipes/resource_action_spec.rb54
-rw-r--r--spec/integration/recipes/resource_converge_if_changed_spec.rb86
-rw-r--r--spec/spec_helper.rb19
-rw-r--r--spec/support/lib/chef/resource/one_two_three_four.rb2
-rw-r--r--spec/support/lib/chef/resource/zen_master.rb4
-rw-r--r--spec/support/mock/constant.rb2
-rw-r--r--spec/support/shared/functional/execute_resource.rb2
-rw-r--r--spec/support/shared/integration/knife_support.rb5
-rw-r--r--spec/support/shared/unit/application_dot_d.rb2
-rw-r--r--spec/support/shared/unit/execute_resource.rb9
-rw-r--r--spec/support/shared/unit/provider/file.rb10
-rw-r--r--spec/unit/application/solo_spec.rb9
-rw-r--r--spec/unit/audit/audit_reporter_spec.rb6
-rw-r--r--spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb82
-rw-r--r--spec/unit/chef_fs/file_system/repository/directory_spec.rb4
-rw-r--r--spec/unit/chef_fs/file_system_spec.rb2
-rw-r--r--spec/unit/client_spec.rb13
-rw-r--r--spec/unit/cookbook/synchronizer_spec.rb30
-rw-r--r--spec/unit/cookbook_loader_spec.rb12
-rw-r--r--spec/unit/cookbook_manifest_spec.rb4
-rw-r--r--spec/unit/data_collector/resource_report_spec.rb6
-rw-r--r--spec/unit/deprecated_spec.rb8
-rw-r--r--spec/unit/dsl/recipe_spec.rb13
-rw-r--r--spec/unit/environment_spec.rb4
-rw-r--r--spec/unit/http_spec.rb9
-rw-r--r--spec/unit/knife/bootstrap_spec.rb5
-rw-r--r--spec/unit/knife/configure_spec.rb70
-rw-r--r--spec/unit/knife/cookbook_test_spec.rb4
-rw-r--r--spec/unit/knife/core/gem_glob_loader_spec.rb4
-rw-r--r--spec/unit/knife/core/node_editor_spec.rb4
-rw-r--r--spec/unit/knife/data_bag_create_spec.rb50
-rw-r--r--spec/unit/knife/data_bag_show_spec.rb18
-rw-r--r--spec/unit/knife/environment_compare_spec.rb6
-rw-r--r--spec/unit/knife/index_rebuild_spec.rb125
-rw-r--r--spec/unit/knife/node_policy_set_spec.rb122
-rw-r--r--spec/unit/knife/ssh_spec.rb124
-rw-r--r--spec/unit/knife_spec.rb2
-rw-r--r--spec/unit/lwrp_spec.rb8
-rw-r--r--spec/unit/mixin/openssl_helper_spec.rb252
-rw-r--r--spec/unit/mixin/params_validate_spec.rb13
-rw-r--r--spec/unit/mixin/powershell_type_coercions_spec.rb13
-rw-r--r--spec/unit/mixin/properties_spec.rb14
-rw-r--r--spec/unit/mixin/user_context_spec.rb3
-rw-r--r--spec/unit/node/attribute_spec.rb100
-rw-r--r--spec/unit/node/immutable_collections_spec.rb54
-rw-r--r--spec/unit/node/vivid_mash_spec.rb37
-rw-r--r--spec/unit/node_map_spec.rb36
-rw-r--r--spec/unit/node_spec.rb16
-rw-r--r--spec/unit/property/validation_spec.rb9
-rw-r--r--spec/unit/property_spec.rb26
-rw-r--r--spec/unit/provider/deploy/revision_spec.rb110
-rw-r--r--spec/unit/provider/deploy/timestamped_spec.rb40
-rw-r--r--spec/unit/provider/deploy_spec.rb641
-rw-r--r--spec/unit/provider/erl_call_spec.rb77
-rw-r--r--spec/unit/provider/group/dscl_spec.rb19
-rw-r--r--spec/unit/provider/ifconfig_spec.rb13
-rw-r--r--spec/unit/provider/mount/mount_spec.rb22
-rw-r--r--spec/unit/provider/package/apt_spec.rb804
-rw-r--r--spec/unit/provider/package/chocolatey_spec.rb4
-rw-r--r--spec/unit/provider/package/powershell_spec.rb94
-rw-r--r--spec/unit/provider/package/rubygems_spec.rb5
-rw-r--r--spec/unit/provider/package/zypper_spec.rb8
-rw-r--r--spec/unit/provider/package_spec.rb62
-rw-r--r--spec/unit/provider/remote_file/http_spec.rb42
-rw-r--r--spec/unit/provider/remote_file/network_file_spec.rb2
-rw-r--r--spec/unit/provider/route_spec.rb2
-rw-r--r--spec/unit/provider/service/solaris_smf_service_spec.rb11
-rw-r--r--spec/unit/provider/service/systemd_service_spec.rb12
-rw-r--r--spec/unit/provider/service/windows_spec.rb451
-rw-r--r--spec/unit/provider/systemd_unit_spec.rb63
-rw-r--r--spec/unit/provider/user/dscl_spec.rb26
-rw-r--r--spec/unit/provider/windows_task_spec.rb190
-rw-r--r--spec/unit/provider/zypper_repository_spec.rb124
-rw-r--r--spec/unit/provider_resolver_spec.rb9
-rw-r--r--spec/unit/provider_spec.rb2
-rw-r--r--spec/unit/recipe_spec.rb8
-rw-r--r--spec/unit/resource/apt_package_spec.rb6
-rw-r--r--spec/unit/resource/apt_preference_spec.rb5
-rw-r--r--spec/unit/resource/apt_repository_spec.rb10
-rw-r--r--spec/unit/resource/apt_update_spec.rb5
-rw-r--r--spec/unit/resource/bash_spec.rb17
-rw-r--r--spec/unit/resource/batch_spec.rb7
-rw-r--r--spec/unit/resource/cab_package_spec.rb24
-rw-r--r--spec/unit/resource/chef_gem_spec.rb6
-rw-r--r--spec/unit/resource/chocolatey_package_spec.rb22
-rw-r--r--spec/unit/resource/conditional_spec.rb4
-rw-r--r--spec/unit/resource/cookbook_file_spec.rb54
-rw-r--r--spec/unit/resource/cron_spec.rb160
-rw-r--r--spec/unit/resource/csh_spec.rb17
-rw-r--r--spec/unit/resource/deploy_revision_spec.rb42
-rw-r--r--spec/unit/resource/deploy_spec.rb283
-rw-r--r--spec/unit/resource/directory_spec.rb58
-rw-r--r--spec/unit/resource/dnf_package_spec.rb64
-rw-r--r--spec/unit/resource/env_spec.rb50
-rw-r--r--spec/unit/resource/erl_call_spec.rb81
-rw-r--r--spec/unit/resource/execute_spec.rb12
-rw-r--r--spec/unit/resource/file/verification_spec.rb22
-rw-r--r--spec/unit/resource/file_spec.rb109
-rw-r--r--spec/unit/resource/freebsd_package_spec.rb57
-rw-r--r--spec/unit/resource/gem_package_spec.rb10
-rw-r--r--spec/unit/resource/git_spec.rb17
-rw-r--r--spec/unit/resource/group_spec.rb129
-rw-r--r--spec/unit/resource/homebrew_package_spec.rb4
-rw-r--r--spec/unit/resource/http_request_spec.rb34
-rw-r--r--spec/unit/resource/ifconfig_spec.rb6
-rw-r--r--spec/unit/resource/ips_package_spec.rb10
-rw-r--r--spec/unit/resource/ksh_spec.rb17
-rw-r--r--spec/unit/resource/launchd_spec.rb30
-rw-r--r--spec/unit/resource/link_spec.rb105
-rw-r--r--spec/unit/resource/log_spec.rb51
-rw-r--r--spec/unit/resource/mdadm_spec.rb85
-rw-r--r--spec/unit/resource/mount_spec.rb197
-rw-r--r--spec/unit/resource/msu_package_spec.rb26
-rw-r--r--spec/unit/resource/ohai_spec.rb31
-rw-r--r--spec/unit/resource/openbsd_package_spec.rb24
-rw-r--r--spec/unit/resource/openssl_dhparam.rb51
-rw-r--r--spec/unit/resource/openssl_rsa_private_key.rb59
-rw-r--r--spec/unit/resource/openssl_rsa_public_key.rb (renamed from spec/unit/resource/timestamped_deploy_spec.rb)29
-rw-r--r--spec/unit/resource/osx_profile_spec.rb17
-rw-r--r--spec/unit/resource/package_spec.rb75
-rw-r--r--spec/unit/resource/perl_spec.rb18
-rw-r--r--spec/unit/resource/portage_package_spec.rb18
-rw-r--r--spec/unit/resource/powershell_package_spec.rb20
-rw-r--r--spec/unit/resource/python_spec.rb18
-rw-r--r--spec/unit/resource/reboot_spec.rb45
-rw-r--r--spec/unit/resource/registry_key_spec.rb181
-rw-r--r--spec/unit/resource/remote_directory_spec.rb81
-rw-r--r--spec/unit/resource/remote_file_spec.rb156
-rw-r--r--spec/unit/resource/route_spec.rb85
-rw-r--r--spec/unit/resource/rpm_package_spec.rb14
-rw-r--r--spec/unit/resource/ruby_block_spec.rb29
-rw-r--r--spec/unit/resource/ruby_spec.rb19
-rw-r--r--spec/unit/resource/scm_spec.rb135
-rw-r--r--spec/unit/resource/script_spec.rb2
-rw-r--r--spec/unit/resource/service_spec.rb162
-rw-r--r--spec/unit/resource/smartos_package_spec.rb5
-rw-r--r--spec/unit/resource/solaris_package_spec.rb8
-rw-r--r--spec/unit/resource/subversion_spec.rb34
-rw-r--r--spec/unit/resource/systemd_unit_spec.rb110
-rw-r--r--spec/unit/resource/template_spec.rb115
-rw-r--r--spec/unit/resource/user_spec.rb99
-rw-r--r--spec/unit/resource/windows_package_spec.rb6
-rw-r--r--spec/unit/resource/windows_path_spec.rb19
-rw-r--r--spec/unit/resource/windows_service_spec.rb29
-rw-r--r--spec/unit/resource/windows_task_spec.rb181
-rw-r--r--spec/unit/resource/yum_package_spec.rb2
-rw-r--r--spec/unit/resource/yum_repository_spec.rb69
-rw-r--r--spec/unit/resource/zypper_repository_spec.rb55
-rw-r--r--spec/unit/resource_spec.rb36
-rw-r--r--spec/unit/util/dsc/lcm_output_parser_spec.rb120
-rw-r--r--spec/unit/util/dsc/local_configuration_manager_spec.rb3
-rw-r--r--spec/unit/util/selinux_spec.rb9
-rw-r--r--spec/unit/util/windows/logon_session_spec.rb3
-rw-r--r--spec/unit/win32/security_spec.rb51
-rw-r--r--tasks/cbgb.rb2
-rw-r--r--tasks/dependencies.rb5
-rw-r--r--tasks/maintainers.rb6
-rw-r--r--tasks/rspec.rb2
480 files changed, 9254 insertions, 8863 deletions
diff --git a/.expeditor/config.yml b/.expeditor/config.yml
index 23c9a981df..8a856ee5ba 100644
--- a/.expeditor/config.yml
+++ b/.expeditor/config.yml
@@ -1,4 +1,4 @@
-# Documentation available at http://http://expeditor-docs.es.chef.io/
+# Documentation available at https://expeditor-docs.es.chef.io/
# The name of the product keys for this product (from mixlib-install)
product_key:
@@ -15,6 +15,9 @@ rubygems:
- chef
- chef-config
+docker_images:
+ - chef
+
github:
# The file where the MAJOR.MINOR.PATCH version is kept. The version in this file
# is bumped automatically via the `built_in:bump_version` merge_action.
@@ -31,25 +34,30 @@ github:
# for building.
release_branch:
- master:
- version_constraint: ~> 13.0
+ version_constraint: 14.*
+ - chef-13:
+ version_constraint: 13.*
- chef-12:
- version_constraint: ~> 12.0
+ version_constraint: 12.*
# These actions are taken, in order they are specified, anytime a Pull Request is merged.
merge_actions:
- built_in:bump_version:
ignore_labels:
- "Version: Skip Bump"
+ - "Expeditor: Skip Version Bump"
- "Expeditor: Skip All"
- bash:.expeditor/update_version.sh:
only_if: built_in:bump_version
- built_in:update_changelog:
ignore_labels:
- "Meta: Exclude From Changelog"
+ - "Expeditor: Exclude From Changelog"
- "Expeditor: Skip All"
- built_in:trigger_omnibus_release_build:
ignore_labels:
- "Omnibus: Skip Build"
+ - "Expeditor: Skip Build"
- "Expeditor: Skip All"
only_if: built_in:bump_version
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 00e1134964..fee8d42d91 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,4 +1,4 @@
# Order is important. The last matching pattern has the most precedence.
* @chef/client-maintainers
-.expeditor/** @chef/engineering-services
+.expeditor/** @chef/jex-team
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index d6ca06036d..c6f0984993 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,36 +1,37 @@
-## Description
+<!---
+!!!!!! NOTE: CHEF CLIENT BUGS ONLY !!!!!!
-Briefly describe the issue
+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.
-## Chef Version
+* 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)
-Tell us which version of chef-client you are using (see below for Server+ChefDK bugs).
+-->
-## Platform Version
+## Description
+<!--- Briefly describe the issue -->
-Tell us which Operating System distribution and version chef-client is running on.
+## Chef Version
+<!--- Tell us which version of chef-client you are using (see below for Server+ChefDK bugs). -->
-## Replication Case
+## Platform Version
+<!--- Tell us which Operating System distribution and version chef-client is running on. -->
-Tell us what steps to take to replicate your problem. See [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve)
-for information on how to create a good replication case.
+## Replication Case
+<!--- Tell us what steps to take to replicate your problem. See [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve)
+for information on how to create a good replication case. -->
## Client Output
+<!--- The relevant output of the chef-client run or a link to a gist of the entire run, if there is one.
-The relevant output of the chef-client run or a link to a gist of the entire run, if there is one.
-
-The debug output (chef-client -l debug) may be useful, but please link to a gist, or truncate it.
-
-## Stacktrace
-
-Please include the stacktrace.out output or link to a gist of it, if there is one.
+The debug output (chef-client -l debug) may be useful, but please link to a gist, or truncate it. -->
-### NOTE: CHEF CLIENT BUGS ONLY
+```
-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.
+```
-* 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)
+## Stacktrace
+<!--- Please include the stacktrace.out output or link to a gist of it, if there is one. -->
diff --git a/.gitignore b/.gitignore
index 3a32f47541..35aecf92cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,8 +39,10 @@ doc/
Vagrantfile
.vagrant/
-# Kitchen Tests Local Mode Data
+# Kitchen Tests lock files and chef data
kitchen-tests/nodes/*
+kitchen-tests/Gemfile.lock
+kitchen-tests/Berksfile.lock
# Temporary files present during spec runs
spec/data/test-dir
diff --git a/.mailmap b/.mailmap
index 614100091a..142d587a4e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -168,3 +168,7 @@ Peter Burkholder <pburkholder@chef.io> Peter Burkholder <peterb@getchef.com>
# JJ Ashgar
JJ Asghar <jj@chef.io> JJ Asghar <jj@getchef.com>
+
+# Tim Smith
+Tim Smith <tsmith@chef.io> Tim Smith <tim@cozy.co>
+Tim Smith <tsmith@chef.io> Tim Smith <tsmith84@gmail.co>
diff --git a/.travis.yml b/.travis.yml
index c4562a808e..db5edab1ad 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,4 @@
language: ruby
-sudo: false
cache: bundler
dist: trusty
@@ -7,7 +6,10 @@ dist: trusty
before_install:
- gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
- gem --version
- - rvm @global do gem uninstall bundler -a -x
+ # travis may preinstall a bundler gem which is later than the one which we pin, which may totally hose us, so we preemtively
+ # uninstall anything they may have installed here. if they haven't installed anything then we have to ignore the failure
+ # to uninstall the default bundler that ships embedded in ruby itself.
+ - rvm @global do gem uninstall bundler -a -x || true
- gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
- bundle --version
- rm -f .bundle/config
@@ -17,12 +19,13 @@ before_script:
- echo --color > .rspec
- echo -fp >> .rspec
# necessary for sudo: true tests, ingore failures on tests invoked with sudo: false
- - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers || true
+ - sudo sed -i -e 's/^Defaults\tsecure_path.*$//' /etc/sudoers
# do not run expensive spec tests on PRs, only on branches
branches:
only:
- master
+ - chef-13
- chef-12
env:
@@ -31,25 +34,55 @@ env:
matrix:
include:
- - rvm: 2.3.5
+ - env:
+ INTEGRATION_SPECS_24: 1
+ rvm: 2.4.3
sudo: true
- script: sudo -E $(which bundle) exec rake spec;
- # also remove integration / external tests
+ script: sudo -E $(which bundle) exec rake spec:integration;
bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
- - rvm: 2.4.2
+ - env:
+ INTEGRATION_SPECS_25: 1
+ rvm: 2.5.0
sudo: true
- script: sudo -E $(which bundle) exec rake spec;
- # also remove integration / external tests
+ script: sudo -E $(which bundle) exec rake spec:integration;
+ bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
+ - env:
+ FUNCTIONAL_SPECS_24: 1
+ rvm: 2.4.3
+ sudo: true
+ script: sudo -E $(which bundle) exec rake spec:functional;
+ bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
+ - env:
+ FUNCTIONAL_SPECS_25: 1
+ rvm: 2.5.0
+ sudo: true
+ script: sudo -E $(which bundle) exec rake spec:functional;
+ bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
+ - env:
+ UNIT_SPECS_24: 1
+ rvm: 2.4.3
+ sudo: true
+ script:
+ - sudo -E $(which bundle) exec rake spec:unit;
+ - sudo -E $(which bundle) exec rake component_specs
+ bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
+ - env:
+ UNIT_SPECS_25: 1
+ rvm: 2.5.0
+ sudo: true
+ script:
+ - sudo -E $(which bundle) exec rake spec:unit;
+ - sudo -E $(which bundle) exec rake component_specs
bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
- env:
CHEFSTYLE: 1
- rvm: 2.4.2
+ rvm: 2.5.0
script: bundle exec rake style
# also remove integration / external tests
bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
- env:
AUDIT_CHECK: 1
- rvm: 2.4.2
+ rvm: 2.5.0
script: bundle exec bundle-audit check --update
# also remove integration / external tests
bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
@@ -59,100 +92,100 @@ matrix:
- env:
TEST_GEM: sethvargo/chef-sugar
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
PEDANT_OPTS: --skip-oc_id
TEST_GEM: chef/chef-zero
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake spec cheffs
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
TEST_GEM: chef/cheffish
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake spec
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
TEST_GEM: chefspec/chefspec
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
TEST_GEM: foodcritic/foodcritic
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake test
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
TEST_GEM: poise/halite
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake spec
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
TEST_GEM: chef/knife-windows
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake unit_spec
- rvm: 2.4.2
+ rvm: 2.5.0
- env:
TEST_GEM: poise/poise
script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake spec
- rvm: 2.4.2
+ rvm: 2.5.0
+ - env:
+ TEST_GEM: chef/knife-windows
+ script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake unit_spec
+ rvm: 2.5.0
### START TEST KITCHEN ONLY ###
#
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
script:
- - bundle exec kitchen test base-ubuntu-1404
+ - bundle exec kitchen test base-amazonlinux
after_failure:
- cat .kitchen/logs/kitchen.log
env:
- - UBUNTU=14.04
+ - AMAZON=LATEST
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
script:
- - bundle exec kitchen test base-ubuntu-1604
+ - bundle exec kitchen test base-ubuntu-1404
after_failure:
- cat .kitchen/logs/kitchen.log
env:
- - UBUNTU=16.04
+ - UBUNTU=14.04
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
script:
- - bundle exec kitchen test base-debian-7
+ - bundle exec kitchen test base-ubuntu-1604
after_failure:
- cat .kitchen/logs/kitchen.log
env:
- - DEBIAN=7
+ - UBUNTU=16.04
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
@@ -163,14 +196,13 @@ matrix:
env:
- DEBIAN=8
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
@@ -181,14 +213,13 @@ matrix:
env:
- DEBIAN=9
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
@@ -199,14 +230,13 @@ matrix:
env:
- CENTOS=6
- KITCHEN_YAML=.kitchen.travis.yml
- - rvm: 2.4.2
+ - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
before_script:
- sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
- cd kitchen-tests
@@ -217,50 +247,47 @@ matrix:
env:
- CENTOS=7
- KITCHEN_YAML=.kitchen.travis.yml
-# - rvm: 2.4.2
-# services: docker
-# sudo: required
-# gemfile: kitchen-tests/Gemfile
-# before_install:
-# - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
-# - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
-# bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
-# before_script:
-# - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
-# - cd kitchen-tests
-# script:
-# - bundle exec kitchen test base-fedora-latest
-# after_failure:
-# - cat .kitchen/logs/kitchen.log
-# env:
-# - FEDORA=latest
-# - KITCHEN_YAML=.kitchen.travis.yml
-# - rvm: 2.4.2
-# services: docker
-# sudo: required
-# gemfile: kitchen-tests/Gemfile
-# before_install:
-# - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
-# - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
-# bundler_args: --without ci docgen guard integration maintenance omnibus_package --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 base-amazonlinux
-# after_failure:
-# - cat .kitchen/logs/kitchen.log
-# env:
-# - AMAZONLINUX=LATEST
-# - KITCHEN_YAML=.kitchen.travis.yml
-# - rvm: 2.4.2
+ - rvm: 2.4.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)
+ before_script:
+ - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
+ - cd kitchen-tests
+ script:
+ - bundle exec kitchen test base-fedora-latest
+ after_failure:
+ - cat .kitchen/logs/kitchen.log
+ env:
+ - FEDORA=latest
+ - KITCHEN_YAML=.kitchen.travis.yml
+ - rvm: 2.4.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)
+ before_script:
+ - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
+ - cd kitchen-tests
+ script:
+ - bundle exec kitchen test base-opensuse-leap
+ after_failure:
+ - cat .kitchen/logs/kitchen.log
+ env:
+ - OPENSUSELEAP=42
+ - KITCHEN_YAML=.kitchen.travis.yml
+# - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
# before_script:
# - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
# - cd kitchen-tests
@@ -271,14 +298,13 @@ matrix:
# env:
# - AWESOME_CUSTOMERS_UBUNTU=1
# - KITCHEN_YAML=.kitchen.travis.yml
-# - rvm: 2.4.2
+# - rvm: 2.4.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 ci docgen guard integration maintenance omnibus_package --frozen
# before_script:
# - sudo iptables -L DOCKER || ( echo "DOCKER iptables chain missing" ; sudo iptables -N DOCKER )
# - cd kitchen-tests
@@ -290,14 +316,14 @@ matrix:
# - AWESOME_CUSTOMERS_RHEL=1
# - KITCHEN_YAML=.kitchen.travis.yml
# ### END TEST KITCHEN ONLY ###
- - rvm: 2.4.2
+ - rvm: 2.5.0
sudo: required
before_install:
- gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
+ - rvm @global do gem uninstall bundler -a -x || true
- gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
- sudo apt-get update
- sudo apt-get -y install squid3 git curl
- bundler_args: --without ci docgen guard integration maintenance omnibus_package --frozen
env:
- PROXY_TESTS_DIR=proxy_tests/files/default/scripts
- PROXY_TESTS_REPO=$PROXY_TESTS_DIR/repo
@@ -309,38 +335,9 @@ matrix:
- cat /tmp/out.txt
- sudo cat /var/log/squid3/cache.log
- sudo cat /var/log/squid3/access.log
- allow_failures:
- - rvm: 2.4.2
- services: docker
- sudo: required
- gemfile: kitchen-tests/Gemfile
- before_install:
- - gem update --system $(grep rubygems omnibus_overrides.rb | cut -d'"' -f2)
- - gem install bundler -v $(grep bundler omnibus_overrides.rb | cut -d'"' -f2)
- bundler_args: --without ci docgen guard integration maintenance omnibus_package --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 base-amazonlinux
- after_failure:
- - cat .kitchen/logs/kitchen.log
- env:
- - AMAZONLINUX=LATEST
- - KITCHEN_YAML=.kitchen.travis.yml
- # this has been broken for some time and running incorrectly, see:
- #
- # see https://github.com/chef/knife-windows/pull/421
- - env:
- TEST_GEM: chef/knife-windows
- script: bundle exec tasks/bin/run_external_test $TEST_GEM master rake unit_spec
- rvm: 2.4.2
notifications:
on_change: true
on_failure: true
on_success: change
on_pull_requests: false
- irc:
- channels:
- - chat.freenode.net#chef-hacking
diff --git a/CHANGELOG.md b/CHANGELOG.md
index adf59f5e20..4e6a0b9347 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,32 +1,206 @@
<!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
-<!-- latest_release 13.4.30 -->
-## [v13.4.30](https://github.com/chef/chef/tree/v13.4.30) (2017-09-18)
+<!-- latest_release 14.0.52 -->
+## [v14.0.52](https://github.com/chef/chef/tree/v14.0.52) (2018-02-12)
#### Merged Pull Requests
-- Update dokken integration testing: dokken images, updated cookbook, debian 9 [#6414](https://github.com/chef/chef/pull/6414) ([tas50](https://github.com/tas50))
+- Implement resource enhancement RFCs [#6818](https://github.com/chef/chef/pull/6818) ([thommay](https://github.com/thommay))
<!-- latest_release -->
-<!-- release_rollup since=13.4.24 -->
-### Changes since 13.4.24 release
+<!-- release_rollup since=13.7.16 -->
+### Changes since 13.7.16 release
#### Merged Pull Requests
-- Update dokken integration testing: dokken images, updated cookbook, debian 9 [#6414](https://github.com/chef/chef/pull/6414) ([tas50](https://github.com/tas50)) <!-- 13.4.30 -->
-- Don&#39;t catch SIGCHLD from dnf_helper.py [#6416](https://github.com/chef/chef/pull/6416) ([nemith](https://github.com/nemith)) <!-- 13.4.29 -->
-- Open apt resources up to prevent breaking change [#6417](https://github.com/chef/chef/pull/6417) ([tas50](https://github.com/tas50)) <!-- 13.4.28 -->
-- Remove unused requires in yum_repository [#6413](https://github.com/chef/chef/pull/6413) ([tas50](https://github.com/tas50)) <!-- 13.4.27 -->
-- Quiet the output of the zypper refresh and add force [#6408](https://github.com/chef/chef/pull/6408) ([tas50](https://github.com/tas50)) <!-- 13.4.26 -->
-- Replace which apt-get check with simple debian check in apt resources [#6409](https://github.com/chef/chef/pull/6409) ([tas50](https://github.com/tas50)) <!-- 13.4.25 -->
+- Implement resource enhancement RFCs [#6818](https://github.com/chef/chef/pull/6818) ([thommay](https://github.com/thommay)) <!-- 14.0.52 -->
+- add additional systemd_unit actions [#6835](https://github.com/chef/chef/pull/6835) ([nathwill](https://github.com/nathwill)) <!-- 14.0.51 -->
+- Use the license_scout that comes with Omnibus gem [#6839](https://github.com/chef/chef/pull/6839) ([tduffield](https://github.com/tduffield)) <!-- 14.0.50 -->
+- Simplify powershell_out calls in powershell_package [#6837](https://github.com/chef/chef/pull/6837) ([Happycoil](https://github.com/Happycoil)) <!-- 14.0.49 -->
+- Don&#39;t rely on the Passwd Ohai plugin in resources [#6833](https://github.com/chef/chef/pull/6833) ([thommay](https://github.com/thommay)) <!-- 14.0.48 -->
+- Link to the knife docs when the knife config file is missing [#6364](https://github.com/chef/chef/pull/6364) ([tas50](https://github.com/tas50)) <!-- 14.0.47 -->
+- Grammar fixes in windows_task [#6828](https://github.com/chef/chef/pull/6828) ([Happycoil](https://github.com/Happycoil)) <!-- 14.0.46 -->
+- Fix windows_task idle_time validation [#6807](https://github.com/chef/chef/pull/6807) ([algaut](https://github.com/algaut)) <!-- 14.0.46 -->
+- Remove testing of Debian 7 as it&#39;s going EOL [#6826](https://github.com/chef/chef/pull/6826) ([tas50](https://github.com/tas50)) <!-- 14.0.45 -->
+- guard against somehow being called by the package resource [#6820](https://github.com/chef/chef/pull/6820) ([thommay](https://github.com/thommay)) <!-- 14.0.44 -->
+- Avoid dpkg prompts for modified config files [#6810](https://github.com/chef/chef/pull/6810) ([thommay](https://github.com/thommay)) <!-- 14.0.43 -->
+- Update /etc/fstab on FreeBSD #4959 [#6782](https://github.com/chef/chef/pull/6782) ([cramaechi](https://github.com/cramaechi)) <!-- 14.0.42 -->
+- Remove the spec for epic_fail [#6809](https://github.com/chef/chef/pull/6809) ([tas50](https://github.com/tas50)) <!-- 14.0.41 -->
+- Fix Appveyor testing: the format of this flametest doesn&#39;t matter [#6808](https://github.com/chef/chef/pull/6808) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.40 -->
+- Ensure package (un)locking is idempotent [#6494](https://github.com/chef/chef/pull/6494) ([Rarian](https://github.com/Rarian)) <!-- 14.0.39 -->
+- use a stricter comparison so knife ssh only fails if --exit-on-error [#6582](https://github.com/chef/chef/pull/6582) ([sarkis](https://github.com/sarkis)) <!-- 14.0.38 -->
+- Update error handling for &quot;knife status&quot; #3287 [#6756](https://github.com/chef/chef/pull/6756) ([cramaechi](https://github.com/cramaechi)) <!-- 14.0.37 -->
+- Add create, delete and configure actions to windows_service [#6804](https://github.com/chef/chef/pull/6804) ([jasonwbarnett](https://github.com/jasonwbarnett)) <!-- 14.0.36 -->
+- Add MSIFASTINSTALL property, supported by Windows Installer 5.0 [#6806](https://github.com/chef/chef/pull/6806) ([stuartpreston](https://github.com/stuartpreston)) <!-- 14.0.35 -->
+- Use attempt or attempts in the retries logging [#6802](https://github.com/chef/chef/pull/6802) ([tas50](https://github.com/tas50)) <!-- 14.0.34 -->
+- Remove epic_fail alias to ignore_failure [#6801](https://github.com/chef/chef/pull/6801) ([tas50](https://github.com/tas50)) <!-- 14.0.33 -->
+- Nillable properties are the default now [#6800](https://github.com/chef/chef/pull/6800) ([thommay](https://github.com/thommay)) <!-- 14.0.32 -->
+- Force the creation of a relative link for cacerts [#6798](https://github.com/chef/chef/pull/6798) ([thommay](https://github.com/thommay)) <!-- 14.0.31 -->
+- use a relative link so that docker does not drop our ca bundle link [#6796](https://github.com/chef/chef/pull/6796) ([thommay](https://github.com/thommay)) <!-- 14.0.30 -->
+- fix node assignment of ImmutableArrays to VividMashes/AttrArrays [#6790](https://github.com/chef/chef/pull/6790) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.29 -->
+- allow uninstall of bundler to fail [#6789](https://github.com/chef/chef/pull/6789) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.28 -->
+- [MSYS-724] Chef::Util::Windows::LogonSession should allow having only the prescribed users permissions [#6687](https://github.com/chef/chef/pull/6687) ([NimishaS](https://github.com/NimishaS)) <!-- 14.0.27 -->
+- Added idempotent checks to windows_task_spec [#6761](https://github.com/chef/chef/pull/6761) ([NAshwini](https://github.com/NAshwini)) <!-- 14.0.26 -->
+- update immutable API blacklist and whitelist [#6778](https://github.com/chef/chef/pull/6778) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.25 -->
+- Fix regression where message isn&#39;t an identity property in log resource [#6779](https://github.com/chef/chef/pull/6779) ([tas50](https://github.com/tas50)) <!-- 14.0.24 -->
+- speed up http func tests [#6775](https://github.com/chef/chef/pull/6775) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.23 -->
+- Revert &quot;Fail on interval runs on windows&quot; [#6776](https://github.com/chef/chef/pull/6776) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.22 -->
+- Fix the changelog for the 13.7 release [#6772](https://github.com/chef/chef/pull/6772) ([tas50](https://github.com/tas50)) <!-- 14.0.20 -->
+- Bump to ruby 2.5.0 [#6770](https://github.com/chef/chef/pull/6770) ([thommay](https://github.com/thommay)) <!-- 14.0.19 -->
+- Fail on interval runs on windows [#6766](https://github.com/chef/chef/pull/6766) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.18 -->
+- [MSYS-727] Added support for setting node policy name and group from knife [#6656](https://github.com/chef/chef/pull/6656) ([piyushawasthi](https://github.com/piyushawasthi)) <!-- 14.0.17 -->
+- Convert node map to last-writer-wins for ties [#6765](https://github.com/chef/chef/pull/6765) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.16 -->
+- Remove node.set and node.set_unless attribute levels [#6762](https://github.com/chef/chef/pull/6762) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.15 -->
+- Rename the OpenSSL mixin to avoid name conflicts [#6764](https://github.com/chef/chef/pull/6764) ([tas50](https://github.com/tas50)) <!-- 14.0.14 -->
+- Revert &quot;add create and delete actions for windows_service&quot; [#6763](https://github.com/chef/chef/pull/6763) ([lamont-granquist](https://github.com/lamont-granquist)) <!-- 14.0.13 -->
+- Convert actions in Chef::Resource::Notification to symbols to prevent double notification [#6515](https://github.com/chef/chef/pull/6515) ([dimsh99](https://github.com/dimsh99)) <!-- 14.0.12 -->
+- add create and delete actions for windows_service [#6595](https://github.com/chef/chef/pull/6595) ([jasonwbarnett](https://github.com/jasonwbarnett)) <!-- 14.0.11 -->
+- Fixing missing and/or inconsistent quoting in knife search documentation [#6607](https://github.com/chef/chef/pull/6607) ([andyfeller](https://github.com/andyfeller)) <!-- 14.0.10 -->
+- Remove unused chef_server_fqdn argument: run_status [#6670](https://github.com/chef/chef/pull/6670) ([jasonwbarnett](https://github.com/jasonwbarnett)) <!-- 14.0.9 -->
+- Remove update-rc.d -n (dryrun) option. [#6723](https://github.com/chef/chef/pull/6723) ([vinsonlee](https://github.com/vinsonlee)) <!-- 14.0.8 -->
+- Prevent knife search --id-only from outputting IDs in the same format… [#6742](https://github.com/chef/chef/pull/6742) ([zanecodes](https://github.com/zanecodes)) <!-- 14.0.7 -->
+- Remove deprecated knife ssh --identity-file option [#6445](https://github.com/chef/chef/pull/6445) ([tas50](https://github.com/tas50)) <!-- 14.0.6 -->
+- Add dhparam, rsa_private_key and rsa_public_key resources [#6736](https://github.com/chef/chef/pull/6736) ([tas50](https://github.com/tas50)) <!-- 14.0.5 -->
+- Chef 14: Remove deprecated knife ssh csshx command [#6444](https://github.com/chef/chef/pull/6444) ([tas50](https://github.com/tas50)) <!-- 14.0.4 -->
+- Remove deprecated -r option for Solo mode [#6719](https://github.com/chef/chef/pull/6719) ([tas50](https://github.com/tas50)) <!-- 14.0.3 -->
+- Remove knife index rebuild command that requires Chef &lt; 11 [#6728](https://github.com/chef/chef/pull/6728) ([tas50](https://github.com/tas50)) <!-- 14.0.2 -->
+- Remove erl_call and deploy resources [#6753](https://github.com/chef/chef/pull/6753) ([tas50](https://github.com/tas50)) <!-- 14.0.1 -->
<!-- release_rollup -->
<!-- latest_stable_release -->
+## [v13.7.16](https://github.com/chef/chef/tree/v13.7.16) (2018-01-23)
+
+#### Merged Pull Requests
+- Update release notes for 13.7 [#6751](https://github.com/chef/chef/pull/6751) ([thommay](https://github.com/thommay))
+- Revert deprecation of use_inline_resources [#6754](https://github.com/chef/chef/pull/6754) ([tas50](https://github.com/tas50))
+- fix double-logging bug [#6752](https://github.com/chef/chef/pull/6752) ([lamont-granquist](https://github.com/lamont-granquist))
+- Add a warning that Chef 11 server support in knife user is deprecated [#6725](https://github.com/chef/chef/pull/6725) ([tas50](https://github.com/tas50))
+- fix non-daemonized umask [#6745](https://github.com/chef/chef/pull/6745) ([lamont-granquist](https://github.com/lamont-granquist))
+- simplify node_map logic [#6637](https://github.com/chef/chef/pull/6637) ([lamont-granquist](https://github.com/lamont-granquist))
+- Fix knife status to show seconds when needed #5055 [#6738](https://github.com/chef/chef/pull/6738) ([cramaechi](https://github.com/cramaechi))
+- Enable the deprecation for use_inline_resource [#6732](https://github.com/chef/chef/pull/6732) ([tas50](https://github.com/tas50))
+- Fix dscl group provider gid_used? [#6703](https://github.com/chef/chef/pull/6703) ([get9](https://github.com/get9))
+- Fix windows_task resource not being idempotent for random_delay and execution_time_limit [#6688](https://github.com/chef/chef/pull/6688) ([Vasu1105](https://github.com/Vasu1105))
+- Update to Ruby 2.4.3 [#6737](https://github.com/chef/chef/pull/6737) ([tas50](https://github.com/tas50))
+- DSCL: Check for set home property before file existence (fixes #5777) [#6735](https://github.com/chef/chef/pull/6735) ([get9](https://github.com/get9))
+- Modernize windows_path resource [#6699](https://github.com/chef/chef/pull/6699) ([tas50](https://github.com/tas50))
+- Don&#39;t check both platform_family / os in provides when platform_family will do [#6711](https://github.com/chef/chef/pull/6711) ([tas50](https://github.com/tas50))
+- Update the knife editor error message to point to the correct document [#6726](https://github.com/chef/chef/pull/6726) ([tas50](https://github.com/tas50))
+- Remove a useless regex in zypper_repository resource [#6710](https://github.com/chef/chef/pull/6710) ([tas50](https://github.com/tas50))
+- Deprecate erl_call resource [#6720](https://github.com/chef/chef/pull/6720) ([tas50](https://github.com/tas50))
+- Improve property warnings in resources [#6717](https://github.com/chef/chef/pull/6717) ([tas50](https://github.com/tas50))
+- Remove lock files and test github masters in Kitchen Tests [#6709](https://github.com/chef/chef/pull/6709) ([tas50](https://github.com/tas50))
+- [MSYS-692] Fix issue with PowerShell function buffer [#6664](https://github.com/chef/chef/pull/6664) ([TheLunaticScripter](https://github.com/TheLunaticScripter))
+- Escape single-quoted strings from the context in knife bootstrap [#6695](https://github.com/chef/chef/pull/6695) ([aespinosa](https://github.com/aespinosa))
+- Allow injecting tempfiles into Chef::HTTP [#6701](https://github.com/chef/chef/pull/6701) ([lamont-granquist](https://github.com/lamont-granquist))
+- Modernize launchd resource [#6698](https://github.com/chef/chef/pull/6698) ([tas50](https://github.com/tas50))
+- Add an &#39;s&#39; for quantity of 0 cookbooks. [#6552](https://github.com/chef/chef/pull/6552) ([anoadragon453](https://github.com/anoadragon453))
+- Fix yum_repository allowing priority of 0 and remove string regexes [#6697](https://github.com/chef/chef/pull/6697) ([tas50](https://github.com/tas50))
+- Add descriptions and yard @since comments to all resources [#6696](https://github.com/chef/chef/pull/6696) ([tas50](https://github.com/tas50))
+- Cleanup to some of the resource specs [#6692](https://github.com/chef/chef/pull/6692) ([tas50](https://github.com/tas50))
+- fix for data bag names partially matching search reserved words [#6652](https://github.com/chef/chef/pull/6652) ([sandratiffin](https://github.com/sandratiffin))
+- Modernize directory resource [#6693](https://github.com/chef/chef/pull/6693) ([tas50](https://github.com/tas50))
+- Modernize the ifconfig resource [#6684](https://github.com/chef/chef/pull/6684) ([tas50](https://github.com/tas50))
+- Slight improvements to validation failures [#6690](https://github.com/chef/chef/pull/6690) ([thommay](https://github.com/thommay))
+- Modernize osx_profile resource [#6685](https://github.com/chef/chef/pull/6685) ([tas50](https://github.com/tas50))
+- Modernize cookbook_file resource and expand specs [#6689](https://github.com/chef/chef/pull/6689) ([tas50](https://github.com/tas50))
+- implement credential management [#6660](https://github.com/chef/chef/pull/6660) ([thommay](https://github.com/thommay))
+- Modernize reboot resource and add spec [#6683](https://github.com/chef/chef/pull/6683) ([tas50](https://github.com/tas50))
+- Fix bugs in handling &#39;source&#39; in msu_package and cab_package [#6686](https://github.com/chef/chef/pull/6686) ([tas50](https://github.com/tas50))
+- Move docker and git top cookbook tests to travis [#6673](https://github.com/chef/chef/pull/6673) ([scotthain](https://github.com/scotthain))
+- Modernize the log resource [#6676](https://github.com/chef/chef/pull/6676) ([tas50](https://github.com/tas50))
+- Avoid a few initializers in resources by using the DSL we have [#6671](https://github.com/chef/chef/pull/6671) ([tas50](https://github.com/tas50))
+- Don&#39;t use .match? which is Ruby 2.4+ only in windows_task [#6675](https://github.com/chef/chef/pull/6675) ([tas50](https://github.com/tas50))
+- windows_task: Fix resource isn&#39;t fully idempotent due to command property [#6654](https://github.com/chef/chef/pull/6654) ([Vasu1105](https://github.com/Vasu1105))
+- Invalid date error on windows_task with frequency :on_logon [#6618](https://github.com/chef/chef/pull/6618) ([NimishaS](https://github.com/NimishaS))
+- Fix sneaky chefstyle violations [#6655](https://github.com/chef/chef/pull/6655) ([thommay](https://github.com/thommay))
+- Ensure data bags names can contain reserved words [#6636](https://github.com/chef/chef/pull/6636) ([EmFl](https://github.com/EmFl))
+- windows_task: Add additional input validation to properties [#6628](https://github.com/chef/chef/pull/6628) ([tas50](https://github.com/tas50))
+- Solaris: Fix svcadm clear to only run in maintenance state [#6631](https://github.com/chef/chef/pull/6631) ([jaymalasinha](https://github.com/jaymalasinha))
+- speedup node_map get and set operations [#6632](https://github.com/chef/chef/pull/6632) ([lamont-granquist](https://github.com/lamont-granquist))
+- Update for openssl 1.0.2n and inspec 1.48 [#6630](https://github.com/chef/chef/pull/6630) ([tas50](https://github.com/tas50))
+- Improved windows_task logging [#6617](https://github.com/chef/chef/pull/6617) ([tas50](https://github.com/tas50))
+- Update InSpec to 1.47 and Ohai to 13.7 [#6616](https://github.com/chef/chef/pull/6616) ([tas50](https://github.com/tas50))
+- Add openSUSE testing in Travis &amp; expand cookbooks we test [#6614](https://github.com/chef/chef/pull/6614) ([tas50](https://github.com/tas50))
+- Knife SSH prefix option [#6590](https://github.com/chef/chef/pull/6590) ([mal](https://github.com/mal))
+- Add Amazon Linux testing to PRs in Travis [#6611](https://github.com/chef/chef/pull/6611) ([tas50](https://github.com/tas50))
+- Hide sensitive properties in converge_if_changed. [#6576](https://github.com/chef/chef/pull/6576) ([cma-arnold](https://github.com/cma-arnold))
+- Bump dependencies to pick up InSpec v1.46.2 [#6609](https://github.com/chef/chef/pull/6609) ([adamleff](https://github.com/adamleff))
+- Fix windows_path converging on every run [#6541](https://github.com/chef/chef/pull/6541) ([tas50](https://github.com/tas50))
+- add unit_name name_property to systemd_unit (fixes #6542) [#6546](https://github.com/chef/chef/pull/6546) ([nathwill](https://github.com/nathwill))
+- fix NodeMap to not throw exceptions on platform_versions [#6608](https://github.com/chef/chef/pull/6608) ([lamont-granquist](https://github.com/lamont-granquist))
+- Enable Fedora integration testing in Travis [#6523](https://github.com/chef/chef/pull/6523) ([tas50](https://github.com/tas50))
+- Only warn if a secret was actually given [#6605](https://github.com/chef/chef/pull/6605) ([coderanger](https://github.com/coderanger))
+- Makes life easier for hook authors switching from the older report handler syntax [#6574](https://github.com/chef/chef/pull/6574) ([coderanger](https://github.com/coderanger))
+- [MSYS-688] Fixed invalid date and Invalid starttime error [#6544](https://github.com/chef/chef/pull/6544) ([NimishaS](https://github.com/NimishaS))
+- Selinux shellout fix (#6346) [#6567](https://github.com/chef/chef/pull/6567) ([deltamualpha](https://github.com/deltamualpha))
+- Switch from the Travis container to the VM [#6600](https://github.com/chef/chef/pull/6600) ([btm](https://github.com/btm))
+- Don&#39;t try to uninstall bundler on appveyor [#6597](https://github.com/chef/chef/pull/6597) ([btm](https://github.com/btm))
+- Fix variable name in solaris service provider [#6596](https://github.com/chef/chef/pull/6596) ([jaymalasinha](https://github.com/jaymalasinha))
+- Revert &quot;add missing functional tests for users&quot; [#6588](https://github.com/chef/chef/pull/6588) ([lamont-granquist](https://github.com/lamont-granquist))
+- Filter out periods from tmux session name [#6593](https://github.com/chef/chef/pull/6593) ([afn](https://github.com/afn))
+- Fix mount test, also update ifconfig to work with both common versions. [#6587](https://github.com/chef/chef/pull/6587) ([scotthain](https://github.com/scotthain))
+- Change a useradd_spec test for RHEL &gt;= 6.8 and &gt;= 7.3 [#6555](https://github.com/chef/chef/pull/6555) ([jeremiahsnapp](https://github.com/jeremiahsnapp))
+- replace deprecated Dir.exists? with Dir.exist? [#6583](https://github.com/chef/chef/pull/6583) ([thomasdziedzic](https://github.com/thomasdziedzic))
+- Add ohai_time to minimal_ohai filter [#6584](https://github.com/chef/chef/pull/6584) ([btm](https://github.com/btm))
+<!-- latest_stable_release -->
+
+## [v13.6.4](https://github.com/chef/chef/tree/v13.6.4) (2017-11-06)
+
+#### Merged Pull Requests
+- [MSYS-492]Add missing functional tests for users [#6425](https://github.com/chef/chef/pull/6425) ([harikesh-kolekar](https://github.com/harikesh-kolekar))
+- Fix the invalid version comparison in apt/dpkg providers [#6558](https://github.com/chef/chef/pull/6558) ([tas50](https://github.com/tas50))
+- Fix the invalid version comparison of apt packages. [#6554](https://github.com/chef/chef/pull/6554) ([komazarari](https://github.com/komazarari))
+- Bump openssl and rubygems to latest [#6568](https://github.com/chef/chef/pull/6568) ([tas50](https://github.com/tas50))
+
+## [v13.6.0](https://github.com/chef/chef/tree/v13.6.0) (2017-10-30)
+
+#### Merged Pull Requests
+- Bump InSpec to v1.40.0 [#6460](https://github.com/chef/chef/pull/6460) ([adamleff](https://github.com/adamleff))
+- Force encoding to UTF_8 in chef-shell to prevent failures [#6447](https://github.com/chef/chef/pull/6447) ([tas50](https://github.com/tas50))
+- Only warn about skipping sync once [#6454](https://github.com/chef/chef/pull/6454) ([Happycoil](https://github.com/Happycoil))
+- Import the zypper GPG key before templating the repo [#6410](https://github.com/chef/chef/pull/6410) ([tas50](https://github.com/tas50))
+- Fixes to package upgrade behaviour [#6428](https://github.com/chef/chef/pull/6428) ([jonlives](https://github.com/jonlives))
+- Tweak the knife banners for multi-arg commands. [#6466](https://github.com/chef/chef/pull/6466) ([coderanger](https://github.com/coderanger))
+- dnf_resource: be more specific for rhel packages [#6435](https://github.com/chef/chef/pull/6435) ([NaomiReeves](https://github.com/NaomiReeves))
+- Prevent creation of data bags named node, role, client or environment [#6469](https://github.com/chef/chef/pull/6469) ([sanditiffin](https://github.com/sanditiffin))
+- Remove cookbook_artifacts from CHEF_11_OSS_STATIC_OBJECTS [#6478](https://github.com/chef/chef/pull/6478) ([itmustbejj](https://github.com/itmustbejj))
+- Add allow_downgrade to zypper_package resource [#6476](https://github.com/chef/chef/pull/6476) ([yeoldegrove](https://github.com/yeoldegrove))
+- Don&#39;t spin in powershell module that launches chef processes [#6481](https://github.com/chef/chef/pull/6481) ([ksubrama](https://github.com/ksubrama))
+- Sleep for another interval after handling SIGHUP [#6461](https://github.com/chef/chef/pull/6461) ([grekasius](https://github.com/grekasius))
+- Support new CriticalOhaiPlugins [#6486](https://github.com/chef/chef/pull/6486) ([jaymzh](https://github.com/jaymzh))
+- Package: only RHEL &gt;= 8 and Fedora &gt;= 22 get dnf [#6490](https://github.com/chef/chef/pull/6490) ([lamont-granquist](https://github.com/lamont-granquist))
+- Windows: Added :none frequency to windows_task resource [#6394](https://github.com/chef/chef/pull/6394) ([NAshwini](https://github.com/NAshwini))
+- Fix rebooter for solaris and background reboots [#6497](https://github.com/chef/chef/pull/6497) ([lamont-granquist](https://github.com/lamont-granquist))
+- Added parser for DSC configuration [#6473](https://github.com/chef/chef/pull/6473) ([piyushawasthi](https://github.com/piyushawasthi))
+- Add array support for choco pkg from artifactory [#6437](https://github.com/chef/chef/pull/6437) ([dheerajd-msys](https://github.com/dheerajd-msys))
+- Bump dependencies to pull in new InSpec [#6511](https://github.com/chef/chef/pull/6511) ([adamleff](https://github.com/adamleff))
+- Fix remote_file with UNC paths failing [#6510](https://github.com/chef/chef/pull/6510) ([tas50](https://github.com/tas50))
+- Deprecate the deploy resource and family [#6468](https://github.com/chef/chef/pull/6468) ([coderanger](https://github.com/coderanger))
+- Include Ohai 13.6 [#6521](https://github.com/chef/chef/pull/6521) ([btm](https://github.com/btm))
+- Use the latest libxml2, libxslt, libyaml, and openssl [#6520](https://github.com/chef/chef/pull/6520) ([tas50](https://github.com/tas50))
+- Pull in the latest libiconv and nokogiri [#6532](https://github.com/chef/chef/pull/6532) ([tas50](https://github.com/tas50))
+
+## [v13.5.3](https://github.com/chef/chef/tree/v13.5.3) (2017-10-03)
+
+#### Merged Pull Requests
+- Fix password property is sensitive for mount resource [#6442](https://github.com/chef/chef/pull/6442) ([dimsh99](https://github.com/dimsh99))
+- Only accept MM/DD/YYYY for windows_task start_day [#6434](https://github.com/chef/chef/pull/6434) ([jaym](https://github.com/jaym))
+- Update dependencies to pull in InSpec v1.39.1 [#6440](https://github.com/chef/chef/pull/6440) ([adamleff](https://github.com/adamleff))
+- Fix Knife search ID only option to actually filter result set [#6438](https://github.com/chef/chef/pull/6438) ([dimsh99](https://github.com/dimsh99))
+- Add throttle and metalink options to yum_repository [#6431](https://github.com/chef/chef/pull/6431) ([tas50](https://github.com/tas50))
+- Don&#39;t catch SIGCHLD from dnf_helper.py [#6416](https://github.com/chef/chef/pull/6416) ([nemith](https://github.com/nemith))
+- Open apt resources up to prevent breaking change [#6417](https://github.com/chef/chef/pull/6417) ([tas50](https://github.com/tas50))
+- Remove unused requires in yum_repository [#6413](https://github.com/chef/chef/pull/6413) ([tas50](https://github.com/tas50))
+- Quiet the output of the zypper refresh and add force [#6408](https://github.com/chef/chef/pull/6408) ([tas50](https://github.com/tas50))
+- Replace which apt-get check with simple debian check in apt resources [#6409](https://github.com/chef/chef/pull/6409) ([tas50](https://github.com/tas50))
+
+## [v12.21.14](https://github.com/chef/chef/tree/v12.21.14) (2017-09-27)
+
## [v13.4.24](https://github.com/chef/chef/tree/v13.4.24) (2017-09-14)
#### Merged Pull Requests
-- MSYS-656 - fixed dsc_script for WMF5 [#6383](https://github.com/chef/chef/pull/6383) ([piyushawasthi](https://github.com/piyushawasthi))
-- [MSYS-594] windows_task resource is not idempotent when specifying start_time and start_day [#6312](https://github.com/chef/chef/pull/6312) ([harikesh-kolekar](https://github.com/harikesh-kolekar))
+- Fixed dsc_script for WMF5 [#6383](https://github.com/chef/chef/pull/6383) ([piyushawasthi](https://github.com/piyushawasthi))
+- windows_task resource is not idempotent when specifying start_time and start_day [#6312](https://github.com/chef/chef/pull/6312) ([harikesh-kolekar](https://github.com/harikesh-kolekar))
- Allow specifying default gateway on RHEL/Centos [#6386](https://github.com/chef/chef/pull/6386) ([tomdoherty](https://github.com/tomdoherty))
- Use ruby 2.4.2 to addess multiple security vulnerabilities [#6404](https://github.com/chef/chef/pull/6404) ([thommay](https://github.com/thommay))
-<!-- latest_stable_release -->
## [v13.4.19](https://github.com/chef/chef/tree/v13.4.19) (2017-09-13)
@@ -42,7 +216,7 @@
- Bump Bundler version to 1.15.4 [#6349](https://github.com/chef/chef/pull/6349) ([jakauppila](https://github.com/jakauppila))
- dnf_provider: be more specific when we provide `package` [#6351](https://github.com/chef/chef/pull/6351) ([jaymzh](https://github.com/jaymzh))
- Speed up immutabilization [#6355](https://github.com/chef/chef/pull/6355) ([lamont-granquist](https://github.com/lamont-granquist))
-- node attributes: remove useless dup in merge_all [#6356](https://github.com/chef/chef/pull/6356) ([lamont-granquist](https://github.com/lamont-granquist))
+- Node attributes: remove useless dup in merge_all [#6356](https://github.com/chef/chef/pull/6356) ([lamont-granquist](https://github.com/lamont-granquist))
- Link to the knife docs in both places where we error on editor [#6363](https://github.com/chef/chef/pull/6363) ([tas50](https://github.com/tas50))
- Bump rubygems to 2.6.13 [#6365](https://github.com/chef/chef/pull/6365) ([lamont-granquist](https://github.com/lamont-granquist))
- Ship chef-vault in the omnibus package [#6370](https://github.com/chef/chef/pull/6370) ([thommay](https://github.com/thommay))
@@ -50,20 +224,18 @@
- Immutablize properly as we deep merge [#6362](https://github.com/chef/chef/pull/6362) ([lamont-granquist](https://github.com/lamont-granquist))
- Alternate user local logon authentication for remote_file resource [#5832](https://github.com/chef/chef/pull/5832) ([NimishaS](https://github.com/NimishaS))
- Add support for specifying ETHTOOL_OPTS in the ifconfig resource [#6384](https://github.com/chef/chef/pull/6384) ([tomdoherty](https://github.com/tomdoherty))
-- Cleanup the current changelog [#6387](https://github.com/chef/chef/pull/6387) ([tas50](https://github.com/tas50))
## [v13.3.42](https://github.com/chef/chef/tree/v13.3.42) (2017-08-16)
#### Merged Pull Requests
-- Update Expeditor config to use new Merge and Artifact Actions [#6287](https://github.com/chef/chef/pull/6287) ([tduffield](https://github.com/tduffield))
- Apt: Add apt_preference resource from apt cookbooks [#5529](https://github.com/chef/chef/pull/5529) ([tas50](https://github.com/tas50))
- Fix typos [#6298](https://github.com/chef/chef/pull/6298) ([akitada](https://github.com/akitada))
- Set explicit page size for every search request [#6299](https://github.com/chef/chef/pull/6299) ([stevendanna](https://github.com/stevendanna))
- Add .dockerignore to reduce size of resulting images [#6296](https://github.com/chef/chef/pull/6296) ([tduffield](https://github.com/tduffield))
- Fix git command in DCO sign-off example [#6306](https://github.com/chef/chef/pull/6306) ([edmorley](https://github.com/edmorley))
-- add option to enable unprivileged symlink creation on windows [#6236](https://github.com/chef/chef/pull/6236) ([svmastersamurai](https://github.com/svmastersamurai))
+- Add option to enable unprivileged symlink creation on windows [#6236](https://github.com/chef/chef/pull/6236) ([svmastersamurai](https://github.com/svmastersamurai))
- Bump omnibus-software version [#6310](https://github.com/chef/chef/pull/6310) ([thommay](https://github.com/thommay))
-- throw readable errors if multiple dsc resources are found [#6307](https://github.com/chef/chef/pull/6307) ([Happycoil](https://github.com/Happycoil))
+- Throw readable errors if multiple dsc resources are found [#6307](https://github.com/chef/chef/pull/6307) ([Happycoil](https://github.com/Happycoil))
- Add zypper_repository resource [#5948](https://github.com/chef/chef/pull/5948) ([tas50](https://github.com/tas50))
- Pull in Ohai 13.3 [#6319](https://github.com/chef/chef/pull/6319) ([tas50](https://github.com/tas50))
- Maintain compat with old zypper_repo resource used in cookbooks [#6318](https://github.com/chef/chef/pull/6318) ([tas50](https://github.com/tas50))
@@ -76,12 +248,11 @@
- Added username/password validation for elevated option [\#6293](https://github.com/chef/chef/pull/6293) ([NimishaS](https://github.com/NimishaS))
- Bump mixlib-shellout for \#6271 [\#6285](https://github.com/chef/chef/pull/6285) ([btm](https://github.com/btm))
-- Use new Expeditor config format [\#6272](https://github.com/chef/chef/pull/6272) ([tduffield](https://github.com/tduffield))
- Added :elevated option for powershell\_script resource [\#6271](https://github.com/chef/chef/pull/6271) ([NimishaS](https://github.com/NimishaS))
- Make mount idempotent on Aix [\#6213](https://github.com/chef/chef/pull/6213) ([NAshwini](https://github.com/NAshwini))
- Allow windows\_task create action to update tasks. [\#6193](https://github.com/chef/chef/pull/6193) ([harikesh-kolekar](https://github.com/harikesh-kolekar))
- Use socketless local mode by default [\#6177](https://github.com/chef/chef/pull/6177) ([coderanger](https://github.com/coderanger))
-- convert breakpoint resource to a custom resource [\#6176](https://github.com/chef/chef/pull/6176) ([lamont-granquist](https://github.com/lamont-granquist))
+- Convert breakpoint resource to a custom resource [\#6176](https://github.com/chef/chef/pull/6176) ([lamont-granquist](https://github.com/lamont-granquist))
- Make non-legacy solo use socketless mode [\#6174](https://github.com/chef/chef/pull/6174) ([coderanger](https://github.com/coderanger))
- Prefer Systemd with sysvinit script over Upstart for service provider [\#6157](https://github.com/chef/chef/pull/6157) ([shortdudey123](https://github.com/shortdudey123))
diff --git a/Dockerfile b/Dockerfile
index 2e32d2e452..4c87de012c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,9 +2,9 @@ FROM busybox
MAINTAINER Chef Software, Inc. <docker@chef.io>
ARG CHANNEL=stable
-ARG VERSION=13.4.24
+ARG VERSION=13.6.4
-RUN wget "http://packages.chef.io/files/${CHANNEL}/chef/${VERSION}/el/5/chef-${VERSION}-1.el5.x86_64.rpm" -O /tmp/chef-client.rpm && \
+RUN wget "http://packages.chef.io/files/${CHANNEL}/chef/${VERSION}/el/6/chef-${VERSION}-1.el6.x86_64.rpm" -O /tmp/chef-client.rpm && \
rpm2cpio /tmp/chef-client.rpm | cpio -idmv && \
rm -rf /tmp/chef-client.rpm
diff --git a/Gemfile b/Gemfile
index 14b67daf94..7a5a26bbbc 100644
--- a/Gemfile
+++ b/Gemfile
@@ -7,7 +7,8 @@ source "https://rubygems.org"
# of bundler versions prior to 1.12.0 (https://github.com/bundler/bundler/commit/193a14fe5e0d56294c7b370a0e59f93b2c216eed)
gem "chef", path: "."
-gem "ohai", "~> 13"
+# @todo before shipping 14.0 we need to switch this over to a gem again
+gem "ohai", git: "https://github.com/chef/ohai.git", branch: "master"
gem "chef-config", path: File.expand_path("../chef-config", __FILE__) if File.exist?(File.expand_path("../chef-config", __FILE__))
gem "cheffish", "~> 13" # required for rspec tests
diff --git a/Gemfile.lock b/Gemfile.lock
index 0161561ef8..e4f1c09ae4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,14 +1,32 @@
GIT
remote: https://github.com/chef/chefstyle.git
- revision: 4f1a175179965d53b9f2a068f2ea4c59090454a1
+ revision: 4eb575a63ce5679d9166211d684c9e3fff168d2a
branch: master
specs:
chefstyle (0.6.0)
rubocop (= 0.49.1)
GIT
+ remote: https://github.com/chef/ohai.git
+ revision: 849a4caf9926a4e11f12f9175b6f4dcd8a9ccaf1
+ branch: master
+ specs:
+ ohai (14.0.1)
+ chef-config (>= 12.5.0.alpha.1, < 15)
+ ffi (~> 1.9)
+ ffi-yajl (~> 2.2)
+ ipaddress
+ mixlib-cli
+ mixlib-config (~> 2.0)
+ mixlib-log (>= 1.7.1, < 2.0)
+ mixlib-shellout (~> 2.0)
+ plist (~> 3.1)
+ systemu (~> 2.6.4)
+ wmi-lite (~> 1.0)
+
+GIT
remote: https://github.com/rubysec/bundler-audit.git
- revision: 6e2e298aebb0707a1b62c08c005335ecd130aa66
+ revision: b84d88f76c4d656421c1d810c9760b0fdea5d13a
specs:
bundler-audit (0.6.0)
bundler (~> 1.2)
@@ -17,10 +35,10 @@ GIT
PATH
remote: .
specs:
- chef (13.4.30)
+ chef (14.0.52)
addressable
bundler (>= 1.10)
- chef-config (= 13.4.30)
+ chef-config (= 14.0.52)
chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -36,7 +54,7 @@ PATH
net-sftp (~> 2.1, >= 2.1.2)
net-ssh (>= 2.9, < 5.0)
net-ssh-multi (~> 1.2, >= 1.2.1)
- ohai (~> 13.0)
+ ohai (~> 14.0)
plist (~> 3.2)
proxifier (~> 1.0)
rspec-core (~> 3.5)
@@ -47,10 +65,10 @@ PATH
specinfra (~> 2.10)
syslog-logger (~> 1.6)
uuidtools (~> 2.1.5)
- chef (13.4.30-universal-mingw32)
+ chef (14.0.52-universal-mingw32)
addressable
bundler (>= 1.10)
- chef-config (= 13.4.30)
+ chef-config (= 14.0.52)
chef-zero (>= 13.0)
diff-lcs (~> 1.2, >= 1.2.4)
erubis (~> 2.7)
@@ -67,7 +85,7 @@ PATH
net-sftp (~> 2.1, >= 2.1.2)
net-ssh (>= 2.9, < 5.0)
net-ssh-multi (~> 1.2, >= 1.2.1)
- ohai (~> 13.0)
+ ohai (~> 14.0)
plist (~> 3.2)
proxifier (~> 1.0)
rspec-core (~> 3.5)
@@ -92,11 +110,12 @@ PATH
PATH
remote: chef-config
specs:
- chef-config (13.4.30)
+ chef-config (14.0.52)
addressable
fuzzyurl
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
+ tomlrb (~> 1.2)
GEM
remote: https://rubygems.org/
@@ -105,10 +124,9 @@ GEM
appbundler (0.10.0)
mixlib-cli (~> 1.4)
ast (2.3.0)
- backports (3.8.0)
- binding_of_caller (0.7.2)
+ backports (3.11.0)
+ binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
- blankslate (2.1.2.4)
builder (3.2.3)
byebug (9.1.0)
chef-vault (3.3.0)
@@ -118,29 +136,29 @@ GEM
mixlib-log (~> 1.3)
rack (~> 2.0)
uuidtools (~> 2.1)
- cheffish (13.0.0)
+ cheffish (13.1.0)
chef-zero (~> 13.0)
net-ssh
- coderay (1.1.1)
+ coderay (1.1.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
debug_inspector (0.0.3)
diff-lcs (1.3)
docile (1.1.5)
- docker-api (1.33.6)
- excon (>= 0.38.0)
- json
+ docker-api (1.34.0)
+ excon (>= 0.47.0)
+ multi_json
erubis (2.7.0)
- ethon (0.10.1)
+ ethon (0.11.0)
ffi (>= 1.3.0)
- excon (0.58.0)
- faraday (0.13.1)
+ excon (0.60.0)
+ faraday (0.14.0)
multipart-post (>= 1.2, < 3)
faraday_middleware (0.12.2)
faraday (>= 0.7.4, < 1.0)
- ffi (1.9.18)
- ffi (1.9.18-x64-mingw32)
- ffi (1.9.18-x86-mingw32)
+ ffi (1.9.21)
+ ffi (1.9.21-x64-mingw32)
+ ffi (1.9.21-x86-mingw32)
ffi-win32-extensions (1.0.3)
ffi
ffi-yajl (2.3.1)
@@ -157,13 +175,13 @@ GEM
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- hashdiff (0.3.6)
- hashie (3.5.6)
- highline (1.7.8)
+ hashdiff (0.3.7)
+ hashie (3.5.7)
+ highline (1.7.10)
htmlentities (4.3.4)
httpclient (2.8.3)
iniparse (1.4.4)
- inspec (1.36.1)
+ inspec (1.50.1)
addressable (~> 2.4)
faraday (>= 0.9.0)
hashie (~> 3.4)
@@ -174,15 +192,14 @@ GEM
parallel (~> 1.9)
parslet (~> 1.5)
pry (~> 0)
- rainbow (~> 2)
rspec (~> 3)
rspec-its (~> 1.2)
rubyzip (~> 1.1)
semverse
sslshake (~> 1.2)
thor (~> 0.19)
- toml (~> 0.1)
- train (~> 0.26)
+ tomlrb (~> 1.2)
+ train (~> 0.32)
ipaddress (0.8.3)
iso8601 (0.9.1)
json (2.1.0)
@@ -193,18 +210,18 @@ GEM
logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
- method_source (0.8.2)
+ method_source (0.9.0)
mixlib-archive (0.4.1)
mixlib-log
mixlib-authentication (1.4.2)
mixlib-cli (1.7.0)
- mixlib-config (2.2.4)
+ mixlib-config (2.2.5)
mixlib-log (1.7.1)
mixlib-shellout (2.3.2)
mixlib-shellout (2.3.2-universal-mingw32)
win32-process (~> 0.8.2)
wmi-lite (~> 1.0)
- multi_json (1.12.2)
+ multi_json (1.13.1)
multipart-post (2.0.0)
net-http-persistent (2.9.4)
net-http-pipeline (1.0.1)
@@ -221,33 +238,19 @@ GEM
net-telnet (0.1.1)
netrc (0.11.0)
nori (2.6.0)
- octokit (4.7.0)
+ octokit (4.8.0)
sawyer (~> 0.8.0, >= 0.5.3)
- ohai (13.4.0)
- chef-config (>= 12.5.0.alpha.1, < 14)
- ffi (~> 1.9)
- ffi-yajl (~> 2.2)
- ipaddress
- mixlib-cli
- mixlib-config (~> 2.0)
- mixlib-log (>= 1.7.1, < 2.0)
- mixlib-shellout (~> 2.0)
- plist (~> 3.1)
- systemu (~> 2.6.4)
- wmi-lite (~> 1.0)
- parallel (1.12.0)
- parser (2.4.0.0)
- ast (~> 2.2)
- parslet (1.5.0)
- blankslate (~> 2.0)
- plist (3.3.0)
+ parallel (1.12.1)
+ parser (2.4.0.2)
+ ast (~> 2.3)
+ parslet (1.8.1)
+ plist (3.4.0)
powerpack (0.1.1)
proxifier (1.0.3)
- pry (0.10.4)
+ pry (0.11.3)
coderay (~> 1.1.0)
- method_source (~> 0.8.1)
- slop (~> 3.4)
- pry-byebug (3.5.0)
+ method_source (~> 0.9.0)
+ pry-byebug (3.5.1)
byebug (~> 9.1)
pry (~> 0.10)
pry-remote (0.1.8)
@@ -259,27 +262,27 @@ GEM
pusher-client (0.6.2)
json
websocket (~> 1.0)
- rack (2.0.3)
+ rack (2.0.4)
rainbow (2.2.2)
rake
- rake (12.0.0)
+ rake (12.3.0)
rb-readline (0.5.5)
- rspec (3.6.0)
- rspec-core (~> 3.6.0)
- rspec-expectations (~> 3.6.0)
- rspec-mocks (~> 3.6.0)
- rspec-core (3.6.0)
- rspec-support (~> 3.6.0)
- rspec-expectations (3.6.0)
+ rspec (3.7.0)
+ rspec-core (~> 3.7.0)
+ rspec-expectations (~> 3.7.0)
+ rspec-mocks (~> 3.7.0)
+ rspec-core (3.7.1)
+ rspec-support (~> 3.7.0)
+ rspec-expectations (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.6.0)
+ rspec-support (~> 3.7.0)
rspec-its (1.2.0)
rspec-core (>= 3.0.0)
rspec-expectations (>= 3.0.0)
- rspec-mocks (3.6.0)
+ rspec-mocks (3.7.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.6.0)
- rspec-support (3.6.0)
+ rspec-support (~> 3.7.0)
+ rspec-support (3.7.1)
rspec_junit_formatter (0.2.3)
builder (< 4)
rspec-core (>= 2, < 4, != 2.12.0)
@@ -290,8 +293,8 @@ GEM
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
- ruby-prof (0.16.2)
- ruby-progressbar (1.8.1)
+ ruby-prof (0.17.0)
+ ruby-progressbar (1.9.0)
ruby-shadow (2.5.0)
rubyntlm (0.6.2)
rubyzip (1.2.1)
@@ -300,19 +303,19 @@ GEM
addressable (>= 2.3.5, < 2.6)
faraday (~> 0.8, < 1.0)
semverse (2.0.0)
- serverspec (2.40.0)
+ serverspec (2.41.3)
multi_json
rspec (~> 3.0)
rspec-its
- specinfra (~> 2.68)
+ specinfra (~> 2.72)
sfl (2.3)
- simplecov (0.15.0)
+ simplecov (0.15.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
slop (3.6.0)
- specinfra (2.71.2)
+ specinfra (2.73.2)
net-scp
net-ssh (>= 2.7, < 5.0)
net-telnet
@@ -321,10 +324,8 @@ GEM
syslog-logger (1.6.8)
systemu (2.6.5)
thor (0.20.0)
- toml (0.1.2)
- parslet (~> 1.5.0)
- tomlrb (1.2.4)
- train (0.26.2)
+ tomlrb (1.2.6)
+ train (0.32.0)
docker-api (~> 1.26)
json (>= 1.8, < 3.0)
mixlib-shellout (~> 2.0)
@@ -345,11 +346,11 @@ GEM
ethon (>= 0.8.0)
unicode-display_width (1.3.0)
uuidtools (2.1.5)
- webmock (3.0.1)
+ webmock (3.3.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
- websocket (1.2.4)
+ websocket (1.2.5)
win32-api (1.5.3-universal-mingw32)
win32-dir (0.5.1)
ffi (>= 1.0.0)
@@ -379,13 +380,13 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0, >= 0.6.1)
- winrm-fs (1.0.1)
+ winrm-fs (1.2.0)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
winrm (~> 2.0)
wmi-lite (1.0.0)
- yard (0.9.9)
+ yard (0.9.12)
PLATFORMS
ruby
@@ -403,7 +404,7 @@ DEPENDENCIES
inspec
netrc
octokit
- ohai (~> 13)
+ ohai!
pry
pry-byebug
pry-remote
@@ -419,4 +420,4 @@ DEPENDENCIES
yard
BUNDLED WITH
- 1.15.4
+ 1.16.1
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 3690e12a67..71f1909145 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,164 @@
_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._
+# Unreleased
+
+# Chef Client Release Notes 13.7:
+
+## The `windows_task` Resource should be better behaved
+
+We've spent a considerable amount of time testing and fixing the `windows_task` resource to ensure that it is properly idempotent and correct in more situations.
+
+## Credentials handling
+
+Previously, chef on the workstation used `knife.rb` or `config.rb` to handle credentials. This didn't do a great job when interacting with multiple Chef servers, leading to the need for tools like `knife_block`. We've added support for a credentials file that can contain configuration for many Chef servers (or organizations), and we've made it easy to indicate which account you mean to use.
+
+## New deprecations
+
+### `erl_call` Resource
+
+We introduced `erl_call` to help us to manage CouchDB servers back in the olden times of Chef. Since then, we've noticed that no-one uses it, and so `erl_call` will be removed in Chef 14\. Foodcritic rule FC105 has been introduced to detect usage of erl_call.
+
+### epic_fail
+
+The original name for the ignore_failure property in resources was epic_fail. Our documentation hasn't referred to epic_fail for years and out of the 3500 cookbooks on the Supermarket only one uses epic_fail. In Chef 14 we will remove the epic_fail property entirely. Foodcritic rule FC107 has been introduced to detect usage of epic_fail.
+
+### Legacy Mixins
+
+In Chef 14 several legacy legacy mixins will be removed. Usage of these mixins has resulted in deprecation warnings for several years. They were traditionally used in some HWRPs, but are rarely found in code available on the Supermarket. Foodcritic rules FC097, FC098, FC099, FC100, and FC102 have been introduced to detect these mixins.
+
+- Chef::Mixin::LanguageIncludeAttribute
+- Chef::Mixin::RecipeDefinitionDSLCore
+- Chef::Mixin::LanguageIncludeRecipe
+- Chef::Mixin::Language
+- Chef::DSL::Recipe::FullDSL
+
+### :uninstall action in chocolatey_package
+
+The chocolatey cookbook's chocolatey_package resource originally contained an :uninstall action. When chocolatey_package was moved into core Chef we made :uninstall an alias for :remove. In Chef 14 :uninstall will no longer be a valid action. Foodcritic rule FC103 has been introduced to detect the usage of the :uninstall action.
+
+## Bugfixes
+
+- Resolved a bug where knife commands that prompted on Windows would never display the prompt
+- Fixed hiding of sensitive resources when converge_if_changed was used
+- Fixed scenarios where services would fail to start on Solaris
+
+## Security Updates
+
+- OpenSSL has been upgraded to 1.0.2n to resolve CVE-2017-3738, CVE-2017-3737, CVE-2017-3736, and CVE-2017-3735.
+- Ruby has been upgraded to 2.4.3 to resolve CVE-2017-17405
+
+## Ohai 13.7 Release Notes:
+
+### Network Tunnel Information
+
+The Network plugin on Linux hosts now gathers additional information on tunnels
+
+### LsPci Plugin
+
+The new LsPci plugin provides a `node[:pci]` hash with information about the PCI bus based on `lspci`. Only runs on Linux.
+
+### EC2 C5 Detection
+
+The EC2 plugin has been updated to properly detect the new AWS hypervisor used in the C5 instance types
+
+### mdadm
+
+The mdadm plugin has been updated to properly handle arrays with more than 10 disks and to properly handle journal and spare drives in the disk counts
+
+# Chef Client Release Notes 13.6.4:
+
+## Bugfixes
+
+ - Resolved a regression in 13.6.0 that prevented upgrading packages on Debian/Ubuntu when the package name contained a tilde.
+
+## Security Updates
+
+- OpenSSL has been upgraded to 1.0.2m to resolve CVE-2017-3735 and CVE-2017-3736
+- RubyGems has been upgraded to 2.6.14 to resolve CVE-2017-0903
+
+# Chef Client Release Notes 13.6:
+
+## `deploy` Resource Is Deprecated
+
+The `deploy` resource (and its alter ego `deploy_revision`) have been deprecated,
+to be removed in Chef 14. This is being done because this resource is considered
+overcomplicated and error-prone in the modern Chef ecosystem. A compatibility
+cookbook will be available to help users migrate during the Chef 14 release
+cycle. See [the deprecation documentation](https://docs.chef.io/deprecations_deploy_resource.html)
+for more information.
+
+## zypper\_package supports package downgrades
+
+`zypper_package` now supports downgrading installed packages with the
+`allow_downgrade` property.
+
+## InSpec updated to 1.42.3
+
+## Reserve certain Data Bag names
+
+It's no longer possible to create data bags named `node`, `role`,
+`client`, or `environment`. Existing data bags will continue to work as
+before.
+
+## Properly use yum on RHEL 7
+
+If both dnf and yum were installed, in some circumstances the yum
+provider might choose to run dnf, which is not what we intended it to
+do. It now properly runs yum, all the time.
+
+## Ohai 13.6 Release Notes:
+
+### Critical Plugins
+
+Users can now specify a list of plugins which are `critical`. Critical plugins will cause Ohai to fail if they do not run successfully (and thus cause a Chef run using Ohai to fail). The syntax for this is:
+
+```
+ohai.critical_plugins << :Filesystem
+```
+
+### Filesystem now has a `allow_partial_data` configuration option
+
+The Filesystem plugin now has a `allow_partial_data` configuration option. If set, the filesystem will return whatever data it can even if some commands it ran failed.
+
+### Rackspace detection on Windows
+
+Windows nodes running on Rackspace will now properly detect themselves as running on Rackspace without a hint file.
+
+### Package data on Amazon Linux
+
+The Packages plugin now supports gathering packages data on Amazon Linux
+
+### Deprecation updates
+
+In Ohai 13 we replaced the filesystem and cloud plugins with the filesystem2 and cloud_v2 plugins. To maintain compatibility with users of the previous V2 plugins we write data to both locations. We had originally planned to continue writing data to both locations until Chef 15. Instead due to the large amount of duplicate node data this introduces we are updating OHAI-11 and OHAI-12 deprecations to remove node['cloud_v2'] and node['filesystem2'] with the release of Chef 14 in April 2018.
+
+# Chef Client Release Notes 13.5:
+
+## Mount's password property is now marked as sensitive
+
+This means that passwords passed to mount won't show up in logs.
+
+## The `windows_task` resource now correctly handles `start_day`
+
+Previously, the resource would accept any date that was formatted
+correctly in the local locale, unlike the Windows cookbook and Windows
+itself. We now only support the `MM/DD/YYYY` format, in common with the
+Windows cookbook.
+
+## InSpec updated to 1.39.1
+
+## Ohai 13.5 Release Notes:
+
+### Correctly detect IPv6 routes ending in ::
+
+Previously we would ignore routes that ended `::`, and now we properly
+detect them.
+
+### Plugin run time is now measured
+
+Debug logs will show the length of time each plugin takes to run, making
+debugging of long ohai runs easier.
+
# Chef Client Release Notes 13.4:
## Security release of Ruby
@@ -47,7 +206,7 @@ It is now possible to set `ETHTOOL_OPTS`, `BONDING_OPTS`, `MASTER` and
**Platforms:** Fedora, RHEL, Amazon Linux
Whether the interface is controlled by the channel bonding interface
defined by `master`, above.
-
+
## Chef Vault is now included
Chef Client 13.4 now includes the `chef-vault` gem, making it easier for
diff --git a/VERSION b/VERSION
index ff27ec5ef5..45818a0908 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-13.4.30 \ No newline at end of file
+14.0.52 \ No newline at end of file
diff --git a/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml b/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml
index 699b5e5022..5f6cc7f104 100644
--- a/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml
+++ b/acceptance/.shared/kitchen_acceptance/.kitchen.ec2.yml
@@ -64,17 +64,6 @@ platforms:
image-type: machine
transport:
username: admin
- - name: debian-7
- driver:
- image_search:
- name: debian-wheezy-*
- owner-id: "379101102735"
- architecture: x86_64
- virtualization-type: hvm
- block-device-mapping.volume-type: standard
- image-type: machine
- transport:
- username: admin
#
# Ubuntu
#
diff --git a/acceptance/.shared/kitchen_acceptance/.kitchen.vagrant.yml b/acceptance/.shared/kitchen_acceptance/.kitchen.vagrant.yml
index 954f5e9eb1..6b382cf417 100644
--- a/acceptance/.shared/kitchen_acceptance/.kitchen.vagrant.yml
+++ b/acceptance/.shared/kitchen_acceptance/.kitchen.vagrant.yml
@@ -25,8 +25,6 @@ verifier:
platforms:
<% %w(
debian-8
-debian-7
-debian-6
ubuntu-15.10
ubuntu-14.04
el-7
diff --git a/acceptance/Gemfile b/acceptance/Gemfile
index b466cd0f07..6384ae75d2 100644
--- a/acceptance/Gemfile
+++ b/acceptance/Gemfile
@@ -15,5 +15,5 @@ gem "berkshelf"
# packages are not always immediately available via the omnitruck API.
gem "mixlib-install", "1.2.3"
-# for chef-13 development - pin to the released rubygems version
-gem "chef-config", "< 13.0"
+# for chef-14 development - pin to the released rubygems version
+gem "chef-config", "< 14.0"
diff --git a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb
index 5716b97737..dec292567c 100644
--- a/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb
+++ b/acceptance/top-cookbooks/.acceptance/acceptance-cookbook/libraries/top_cookbooks.rb
@@ -6,12 +6,7 @@ class TopCookbooks < Chef::Resource
# Disabling all windows tests until winrm issue is properly settled.
#
action :run do
- cookbook_kitchen "#{command} docker" do
- end
-
- cookbook_kitchen "#{command} git" do
- end
-
+
# FIXME: waiting for https://github.com/learn-chef/learn-chef-acceptance/pull/23
# cookbook_kitchen "#{command} learn-the-basics-ubuntu" do
# repository "learn-chef/learn-chef-acceptance"
diff --git a/acceptance/top-cookbooks/.kitchen.docker.yml b/acceptance/top-cookbooks/.kitchen.docker.yml
deleted file mode 100644
index 505504268f..0000000000
--- a/acceptance/top-cookbooks/.kitchen.docker.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-suites:
- - name: docker-default
- attributes:
- apt-docker:
- repos:
- docker-main:
- keyserver: hkp://ha.pool.sks-keyservers.net
- docker:
- version: 1.10.0
- run_list:
- - recipe[apt]
- - recipe[chef-apt-docker]
- includes: [ubuntu-14.04]
diff --git a/acceptance/top-cookbooks/.kitchen.git.yml b/acceptance/top-cookbooks/.kitchen.git.yml
deleted file mode 100644
index 302657dffc..0000000000
--- a/acceptance/top-cookbooks/.kitchen.git.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-suites:
- - name: git-default
- # Ubuntu images need to run apt update
- run_list: ["recipe[apt]","recipe[git]"]
- includes: [ubuntu-14.04]
- - name: git-source
- run_list: ["recipe[git::source]"]
- includes: [nonexistent]
- - name: git-default-windows
- run_list: ["recipe[git]"]
- includes: [windows-2012r2]
diff --git a/appveyor.yml b/appveyor.yml
index de947203c1..dde3bb947e 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,13 +1,15 @@
version: "master-{build}"
-os: Visual Studio 2015
+os: Visual Studio 2017
platform:
- x64
+cache:
+- vendor/bundle
+
environment:
matrix:
- ruby_version: "24-x64"
- - ruby_version: "24"
clone_folder: c:\projects\chef
clone_depth: 1
@@ -15,6 +17,7 @@ skip_tags: true
branches:
only:
- master
+ - chef-13
- chef-12
install:
@@ -26,22 +29,22 @@ install:
- echo %OMNIBUS_RUBYGEMS%
- ps: $env:OMNIBUS_BUNDLER=$(findstr bundler omnibus_overrides.rb | %{ $_.split(" ")[3] })
- echo %OMNIBUS_BUNDLER%
- - ruby --version
- gem --version
- - bundler --version
- - gem uninstall bundler -a -x
- gem update --system %OMNIBUS_RUBYGEMS% || gem update --system %OMNIBUS_RUBYGEMS% || gem update --system %OMNIBUS_RUBYGEMS%
- - gem install bundler -v %OMNIBUS_BUNDLER% --quiet --no-ri --no-rdoc || gem install bundler -v %OMNIBUS_BUNDLER% --quiet --no-ri --no-rdoc || gem install bundler -v %OMNIBUS_BUNDLER% --quiet --no-ri --no-rdoc
- - gem --version
- - bundler --version
- - SET BUNDLE_WITHOUT=server:docgen:maintenance:pry:travis:integration:ci
- appveyor DownloadFile http://curl.haxx.se/ca/cacert.pem -FileName C:\cacert.pem
- set SSL_CERT_FILE=C:\cacert.pem
- - bundle env
-
-build_script:
+ - SET BUNDLE_WITHOUT=server:docgen:maintenance:pry:travis:integration:ci
+ - bundle config --local path vendor/bundle # use the cache we define above
- bundle install || bundle install || bundle install
+build: off
+
+before_test:
+ - ruby --version
+ - gem --version
+ - bundler --version
+ - bundle env
+
test_script:
- SET SPEC_OPTS=--format progress
- bundle exec rake spec
diff --git a/bin/chef-shell b/bin/chef-shell
index 4d9300ebb7..9b10aa134b 100755
--- a/bin/chef-shell
+++ b/bin/chef-shell
@@ -23,6 +23,8 @@ begin
rescue LoadError
end
+Encoding.default_external = Encoding::UTF_8
+
require "irb"
require "irb/completion"
require "irb/ext/save-history"
diff --git a/chef-config/.travis.yml b/chef-config/.travis.yml
deleted file mode 100644
index 927580f35f..0000000000
--- a/chef-config/.travis.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-language: ruby
-
-sudo: false
-# Early warning system to catch if Rubygems breaks something
-before_install:
- gem update --system
-
-branches:
- only:
- - master
-
-matrix:
- include:
- - rvm: 2.0
- - rvm: 2.1
-
-notifications:
- on_change: true
- on_failure: true
- on_success: change
- on_pull_requests: false
- irc:
- channels:
- - chat.freenode.net#chef-hacking
- hipchat:
- rooms:
- # Build Statuses
- - secure: G8MNo94L8bmWWwkH2/ViB2QaZnZHZscYM/mEjDbOGd15sqrruwckeARyBoUcRI7P1C6AFmS4IKCNVXa6KzX4Pbh51gQWM92zRpRTZpplwtXz53/1l8ajLFLLMLvEMTlBFAANUKEUFAQPY4dMa14V3Qc5oijfIncN61k4nZNTKpY=
- - rvm: 2.2
- # Open Source
- - secure: hmcex4PpG5dn8WvjndONO4xCUKOC5kPU/bUEGRrfVbe2YKJE7t0XXbNDC96W/xBgzgnJzvf1Er0zJKDrNf4qEDEWFoozdN00WLcqREgaLLS3Seto2FjR/BpBk5q+sCV0rwwEMms2P4Qk+VSnDCnm9EaeM55hOabqNuOrRzoZLBQ=
diff --git a/chef-config/chef-config.gemspec b/chef-config/chef-config.gemspec
index 9e40528fba..1dc1a118ff 100644
--- a/chef-config/chef-config.gemspec
+++ b/chef-config/chef-config.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
spec.add_dependency "mixlib-config", "~> 2.0"
spec.add_dependency "fuzzyurl"
spec.add_dependency "addressable"
+ spec.add_dependency "tomlrb", "~> 1.2"
spec.add_development_dependency "rake", "~> 10.0"
diff --git a/chef-config/lib/chef-config/config.rb b/chef-config/lib/chef-config/config.rb
index beb78f25d0..d5badcc58f 100644
--- a/chef-config/lib/chef-config/config.rb
+++ b/chef-config/lib/chef-config/config.rb
@@ -52,6 +52,12 @@ module ChefConfig
configuration.inspect
end
+ # given a *nix style config path return the platform specific path
+ # to that same config file
+ # @example client.pem path on Windows
+ # platform_specific_path("/etc/chef/client.pem") #=> "C:\\chef\\client.pem"
+ # @param path [String] The unix path to convert to a platform specific path
+ # @return [String] a platform specific path
def self.platform_specific_path(path)
path = PathHelper.cleanpath(path)
if ChefConfig.windows?
@@ -66,6 +72,11 @@ module ChefConfig
path
end
+ # the drive where Chef is installed on a windows host. This is determined
+ # either by the drive containing the current file or by the SYSTEMDRIVE ENV
+ # variable
+ #
+ # @return [String] the drive letter
def self.windows_installation_drive
if ChefConfig.windows?
drive = File.expand_path(__FILE__).split("/", 2)[0]
@@ -249,7 +260,7 @@ module ChefConfig
# Defaults to <chef_repo_path>/policies.
default(:policy_path) { derive_path_from_chef_repo_path("policies") }
- # Turn on "path sanity" by default. See also: http://wiki.opscode.com/display/chef/User+Environment+PATH+Sanity
+ # Turn on "path sanity" by default.
default :enforce_path_sanity, false
# Formatted Chef Client output is a beta feature, disabled by default:
@@ -592,6 +603,12 @@ module ChefConfig
# If chef-zero is enabled, this defaults to nil (no authentication).
default(:client_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/client.pem") }
+ # A credentials file may contain a complete client key, rather than the path
+ # to one.
+ #
+ # We'll use this preferentially.
+ default :client_key_contents, nil
+
# When registering the client, should we allow the client key location to
# be a symlink? eg: /etc/chef/client.pem -> /etc/chef/prod-client.pem
# If the path of the key goes through a directory like /tmp this should
@@ -631,6 +648,7 @@ module ChefConfig
default(:validation_key) { chef_zero.enabled ? nil : platform_specific_path("/etc/chef/validation.pem") }
default :validation_client_name, "chef-validator"
+ default :validation_key_contents, nil
# When creating a new client via the validation_client account, Chef 11
# servers allow the client to generate a key pair locally and send the
# public key to the server. This is more secure and helps offload work from
@@ -691,6 +709,9 @@ module ChefConfig
# on running chef-client
default :count_log_resource_updates, true
+ # The selected profile when using credentials.
+ default :profile, nil
+
# knife configuration data
config_context :knife do
# XXX: none of these default values are applied to knife (and would create a backcompat
diff --git a/chef-config/lib/chef-config/mixin/credentials.rb b/chef-config/lib/chef-config/mixin/credentials.rb
new file mode 100644
index 0000000000..4c0192fff8
--- /dev/null
+++ b/chef-config/lib/chef-config/mixin/credentials.rb
@@ -0,0 +1,57 @@
+#
+# 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 "tomlrb"
+require "chef-config/path_helper"
+
+module ChefConfig
+ module Mixin
+ module Credentials
+
+ def load_credentials(profile = nil)
+ credentials_file = PathHelper.home(".chef", "credentials").freeze
+ context_file = PathHelper.home(".chef", "context").freeze
+
+ return unless File.file?(credentials_file)
+
+ context = File.read(context_file) if File.file?(context_file)
+
+ environment = ENV.fetch("CHEF_PROFILE", nil)
+
+ profile = if !profile.nil?
+ profile
+ elsif !environment.nil?
+ environment
+ elsif !context.nil?
+ context
+ else
+ "default"
+ end
+
+ config = Tomlrb.load_file(credentials_file)
+ apply_credentials(config[profile], profile)
+ rescue ChefConfig::ConfigurationError
+ raise
+ rescue => e
+ # TOML's error messages are mostly rubbish, so we'll just give a generic one
+ message = "Unable to parse Credentials file: #{credentials_file}\n"
+ message << e.message
+ raise ChefConfig::ConfigurationError, message
+ end
+ end
+ end
+end
diff --git a/chef-config/lib/chef-config/path_helper.rb b/chef-config/lib/chef-config/path_helper.rb
index e8a576c84f..c011c4f18a 100644
--- a/chef-config/lib/chef-config/path_helper.rb
+++ b/chef-config/lib/chef-config/path_helper.rb
@@ -235,7 +235,7 @@ module ChefConfig
paths = paths.map { |home_path| home_path.gsub(path_separator, ::File::SEPARATOR) if home_path }
# Filter out duplicate paths and paths that don't exist.
- valid_paths = paths.select { |home_path| home_path && Dir.exists?(home_path.force_encoding("utf-8")) }
+ valid_paths = paths.select { |home_path| home_path && Dir.exist?(home_path.force_encoding("utf-8")) }
valid_paths = valid_paths.uniq
# Join all optional path elements at the end.
diff --git a/chef-config/lib/chef-config/version.rb b/chef-config/lib/chef-config/version.rb
index 3bcd2265cf..7f24c30e1d 100644
--- a/chef-config/lib/chef-config/version.rb
+++ b/chef-config/lib/chef-config/version.rb
@@ -21,7 +21,7 @@
module ChefConfig
CHEFCONFIG_ROOT = File.expand_path("../..", __FILE__)
- VERSION = "13.4.30"
+ VERSION = "14.0.52"
end
#
diff --git a/chef-config/lib/chef-config/workstation_config_loader.rb b/chef-config/lib/chef-config/workstation_config_loader.rb
index babb78aeb8..2738d6a1a2 100644
--- a/chef-config/lib/chef-config/workstation_config_loader.rb
+++ b/chef-config/lib/chef-config/workstation_config_loader.rb
@@ -22,24 +22,31 @@ require "chef-config/logger"
require "chef-config/path_helper"
require "chef-config/windows"
require "chef-config/mixin/dot_d"
+require "chef-config/mixin/credentials"
module ChefConfig
class WorkstationConfigLoader
include ChefConfig::Mixin::DotD
+ include ChefConfig::Mixin::Credentials
# Path to a config file requested by user, (e.g., via command line option). Can be nil
attr_accessor :explicit_config_file
+ # The name of a credentials profile. Can be nil
+ attr_accessor :profile
+ attr_reader :credentials_found
# TODO: initialize this with a logger for Chef and Knife
- def initialize(explicit_config_file, logger = nil)
+ def initialize(explicit_config_file, logger = nil, profile: nil)
@explicit_config_file = explicit_config_file
@chef_config_dir = nil
@config_location = nil
+ @profile = profile
@logger = logger || NullLogger.new
+ @credentials_found = false
end
def no_config_found?
- config_location.nil?
+ config_location.nil? && !credentials_found
end
def config_location
@@ -62,6 +69,7 @@ module ChefConfig
end
def load
+ load_credentials(profile)
# Ignore it if there's no explicit_config_file and can't find one at a
# default path.
if !config_location.nil?
@@ -138,6 +146,38 @@ module ChefConfig
a
end
+ def apply_credentials(creds, profile)
+ Config.profile ||= profile
+ if creds.key?("node_name") && creds.key?("client_name")
+ raise ChefConfig::ConfigurationError, "Do not specify both node_name and client_name. You should prefer client_name."
+ end
+ Config.node_name = creds.fetch("node_name") if creds.key?("node_name")
+ Config.node_name = creds.fetch("client_name") if creds.key?("client_name")
+ Config.chef_server_url = creds.fetch("chef_server_url") if creds.key?("chef_server_url")
+ Config.validation_client_name = creds.fetch("validation_client_name") if creds.key?("validation_client_name")
+
+ extract_key(creds, "validation_key", :validation_key, :validation_key_contents)
+ extract_key(creds, "validator_key", :validation_key, :validation_key_contents)
+ extract_key(creds, "client_key", :client_key, :client_key_contents)
+ @credentials_found = true
+ end
+
+ def extract_key(creds, name, config_path, config_contents)
+ return unless creds.has_key?(name)
+
+ val = creds.fetch(name)
+ if val.start_with?("-----BEGIN RSA PRIVATE KEY-----")
+ Config.send(config_contents, val)
+ else
+ abs_path = Pathname.new(val).expand_path(home_chef_dir)
+ Config.send(config_path, abs_path)
+ end
+ end
+
+ def home_chef_dir
+ @home_chef_dir ||= PathHelper.home(".chef")
+ end
+
def apply_config(config_content, config_file_path)
Config.from_string(config_content, config_file_path)
rescue SignalException
diff --git a/chef-config/spec/unit/workstation_config_loader_spec.rb b/chef-config/spec/unit/workstation_config_loader_spec.rb
index 087f249724..509d95fe36 100644
--- a/chef-config/spec/unit/workstation_config_loader_spec.rb
+++ b/chef-config/spec/unit/workstation_config_loader_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe ChefConfig::WorkstationConfigLoader do
before do
# We set this to nil so that a dev workstation will
# not interfere with the tests.
+ ChefConfig::Config.reset
ChefConfig::Config[:config_d_dir] = nil
end
@@ -363,4 +364,147 @@ RSpec.describe ChefConfig::WorkstationConfigLoader do
end
end
end
+
+ describe "when loading a credentials file" do
+ if ChefConfig.windows?
+ let(:home) { "C:/Users/example.user" }
+ else
+ let(:home) { "/Users/example.user" }
+ end
+ let(:credentials_file) { "#{home}/.chef/credentials" }
+ let(:context_file) { "#{home}/.chef/context" }
+
+ before do
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef").and_return(File.join(home, ".chef"))
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "credentials").and_return(credentials_file)
+ allow(ChefConfig::PathHelper).to receive(:home).with(".chef", "context").and_return(context_file)
+ allow(File).to receive(:file?).with(context_file).and_return false
+ end
+
+ context "when the file exists" do
+ before do
+ expect(File).to receive(:read).with(credentials_file, { encoding: "utf-8" }).and_return(content)
+ allow(File).to receive(:file?).with(credentials_file).and_return true
+ end
+
+ context "and has a default profile" do
+ let(:content) do
+ content = <<EOH
+[default]
+node_name = 'barney'
+client_key = "barney_rubble.pem"
+chef_server_url = "https://api.chef.io/organizations/bedrock"
+EOH
+ content
+ end
+
+ it "applies the expected config" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.chef_server_url).to eq("https://api.chef.io/organizations/bedrock")
+ expect(ChefConfig::Config.client_key.to_s).to eq("#{home}/.chef/barney_rubble.pem")
+ expect(ChefConfig::Config.profile.to_s).to eq("default")
+ end
+ end
+
+ context "and has a profile containing a full key" do
+ let(:content) do
+ content = <<EOH
+[default]
+client_key = """
+-----BEGIN RSA PRIVATE KEY-----
+foo
+"""
+EOH
+ content
+ end
+
+ it "applies the expected config" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.client_key_contents).to eq(<<EOH
+-----BEGIN RSA PRIVATE KEY-----
+foo
+EOH
+)
+ end
+ end
+
+ context "and has several profiles" do
+ let(:content) do
+ content = <<EOH
+[default]
+client_name = "default"
+[environment]
+client_name = "environment"
+[explicit]
+client_name = "explicit"
+[context]
+client_name = "context"
+EOH
+ content
+ end
+
+ let(:env) { {} }
+ before do
+ stub_const("ENV", env)
+ end
+
+ it "selects the correct profile explicitly" do
+ expect { config_loader.load_credentials("explicit") }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("explicit")
+ end
+
+ context "with an environment variable" do
+ let(:env) { { "CHEF_PROFILE" => "environment" } }
+
+ it "selects the correct profile" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("environment")
+ end
+ end
+
+ it "selects the correct profile with a context file" do
+ allow(File).to receive(:file?).with(context_file).and_return true
+ expect(File).to receive(:read).with(context_file).and_return "context"
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("context")
+ end
+
+ it "falls back to the default" do
+ expect { config_loader.load_credentials }.not_to raise_error
+ expect(ChefConfig::Config.node_name).to eq("default")
+ end
+ end
+
+ context "and contains both node_name and client_name" do
+ let(:content) do
+ content = <<EOH
+[default]
+node_name = 'barney'
+client_name = 'barney'
+EOH
+ content
+ end
+
+ it "raises a ConfigurationError" do
+ expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
+ end
+ end
+
+ context "and has a syntax error" do
+ let(:content) { "<<<<<" }
+
+ it "raises a ConfigurationError" do
+ expect { config_loader.load_credentials }.to raise_error(ChefConfig::ConfigurationError)
+ end
+ end
+ end
+
+ context "when the file does not exist" do
+ it "does not load anything" do
+ allow(File).to receive(:file?).with(credentials_file).and_return false
+ expect(Tomlrb).not_to receive(:load_file)
+ config_loader.load_credentials
+ end
+ end
+ end
end
diff --git a/chef.gemspec b/chef.gemspec
index eb187df38f..9dd85d74c6 100644
--- a/chef.gemspec
+++ b/chef.gemspec
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
s.add_dependency "mixlib-authentication", "~> 1.4"
s.add_dependency "mixlib-shellout", "~> 2.0"
s.add_dependency "mixlib-archive", "~> 0.4"
- s.add_dependency "ohai", "~> 13.0"
+ s.add_dependency "ohai", "~> 14.0"
s.add_dependency "ffi-yajl", "~> 2.2"
s.add_dependency "net-ssh", ">= 2.9", "< 5.0"
diff --git a/ci/verify-chef.sh b/ci/verify-chef.sh
index 0c90d65dbe..528152b3b6 100755
--- a/ci/verify-chef.sh
+++ b/ci/verify-chef.sh
@@ -5,7 +5,7 @@ set -evx
# Set up a custom tmpdir, and clean it up before and after the tests
TMPDIR="${TMPDIR:-/tmp}/cheftest"
export TMPDIR
-rm -rf $TMPDIR
+sudo rm -rf $TMPDIR
mkdir -p $TMPDIR
# $PROJECT_NAME is set by Jenkins, this allows us to use the same script to verify
diff --git a/distro/common/html/knife_search.html b/distro/common/html/knife_search.html
index c5006d155e..22d69b11d7 100644
--- a/distro/common/html/knife_search.html
+++ b/distro/common/html/knife_search.html
@@ -51,7 +51,7 @@
</div>
<p>where <tt class="docutils literal"><span class="pre">INDEX</span></tt> is one of <tt class="docutils literal"><span class="pre">client</span></tt>, <tt class="docutils literal"><span class="pre">environment</span></tt>, <tt class="docutils literal"><span class="pre">node</span></tt>, <tt class="docutils literal"><span class="pre">role</span></tt>, or the name of a data bag and <tt class="docutils literal"><span class="pre">SEARCH_QUERY</span></tt> is the search query syntax for the query that will be executed.</p>
<p><tt class="docutils literal"><span class="pre">INDEX</span></tt> is implied if omitted, and will default to <tt class="docutils literal"><span class="pre">node</span></tt>. For example:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search <span class="s1">&#39;*:*&#39;</span> -i
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search <span class="s1">&quot;*:*&quot;</span> -i
</pre></div>
</div>
<p>will return something similar to:</p>
@@ -68,7 +68,7 @@ win2k8-dev
</pre></div>
</div>
<p>and is the same search as:</p>
-<div class="highlight-bash"><div class="highlight"><pre>$ knife search node &#39;*:*&quot; -i
+<div class="highlight-bash"><div class="highlight"><pre>$ knife search node &quot;*:*&quot; -i
</pre></div>
</div>
<p>If the <tt class="docutils literal"><span class="pre">SEARCH_QUERY</span></tt> does not contain a colon character (<tt class="docutils literal"><span class="pre">:</span></tt>), then the default query pattern is <tt class="docutils literal"><span class="pre">tags:*#{&#64;query}*</span> <span class="pre">OR</span> <span class="pre">roles:*#{&#64;query}*</span> <span class="pre">OR</span> <span class="pre">fqdn:*#{&#64;query}*</span> <span class="pre">OR</span> <span class="pre">addresses:*#{&#64;query}*</span></tt>, which means the following two search queries are effectively the same:</p>
@@ -117,7 +117,7 @@ win2k8-dev
<p>The following examples show how to use this knife subcommand:</p>
<p><strong>Search by platform ID</strong></p>
<p>To search for the IDs of all nodes running on the Amazon EC2 platform, enter:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&#39;ec2:*&#39;</span> -i
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&quot;ec2:*&quot;</span> -i
</pre></div>
</div>
<p>to return something like:</p>
@@ -134,7 +134,7 @@ ip-0A7CFFD5.ec2.internal
</div>
<p><strong>Search by instance type</strong></p>
<p>To search for the instance type (flavor) of all nodes running on the Amazon EC2 platform, enter:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&#39;ec2:*&#39;</span> -a ec2.instance_type
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&quot;ec2:*&quot;</span> -a ec2.instance_type
</pre></div>
</div>
<p>to return something like:</p>
@@ -155,12 +155,12 @@ id: ip-0A7CFFD5.ec2.internal
</div>
<p><strong>Search by node</strong></p>
<p>To search for all nodes running Ubuntu, enter:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&#39;platform:ubuntu&#39;</span>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&quot;platform:ubuntu&quot;</span>
</pre></div>
</div>
<p><strong>Search by node and environment</strong></p>
<p>To search for all nodes running CentOS in the production environment, enter:</p>
-<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&#39;chef_environment:production AND platform:centos&#39;</span>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>knife search node <span class="s1">&quot;chef_environment:production AND platform:centos&quot;</span>
</pre></div>
</div>
<p><strong>Search for nested attributes</strong></p>
@@ -200,4 +200,4 @@ id: ip-0A7CFFD5.ec2.internal
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/distro/common/man/man1/knife-search.1 b/distro/common/man/man1/knife-search.1
index 3b81898530..0b87c2d817 100644
--- a/distro/common/man/man1/knife-search.1
+++ b/distro/common/man/man1/knife-search.1
@@ -57,7 +57,7 @@ where \fBINDEX\fP is one of \fBclient\fP, \fBenvironment\fP, \fBnode\fP, \fBrole
.sp
.nf
.ft C
-$ knife search \(aq*:*\(aq \-i
+$ knife search "*:*" \-i
.ft P
.fi
.UNINDENT
@@ -90,7 +90,7 @@ and is the same search as:
.sp
.nf
.ft C
-$ knife search node \(aq*:*" \-i
+$ knife search node "*:*" \-i
.ft P
.fi
.UNINDENT
@@ -218,7 +218,7 @@ To search for the IDs of all nodes running on the Amazon EC2 platform, enter:
.sp
.nf
.ft C
-$ knife search node \(aqec2:*\(aq \-i
+$ knife search node "ec2:*" \-i
.ft P
.fi
.UNINDENT
@@ -250,7 +250,7 @@ To search for the instance type (flavor) of all nodes running on the Amazon EC2
.sp
.nf
.ft C
-$ knife search node \(aqec2:*\(aq \-a ec2.instance_type
+$ knife search node "ec2:*" \-a ec2.instance_type
.ft P
.fi
.UNINDENT
@@ -286,7 +286,7 @@ To search for all nodes running Ubuntu, enter:
.sp
.nf
.ft C
-$ knife search node \(aqplatform:ubuntu\(aq
+$ knife search node "platform:ubuntu"
.ft P
.fi
.UNINDENT
@@ -298,7 +298,7 @@ To search for all nodes running CentOS in the production environment, enter:
.sp
.nf
.ft C
-$ knife search node \(aqchef_environment:production AND platform:centos\(aq
+$ knife search node "chef_environment:production AND platform:centos"
.ft P
.fi
.UNINDENT
diff --git a/distro/common/markdown/man1/knife-search.mkd b/distro/common/markdown/man1/knife-search.mkd
index b289b2c83b..31a1d6e0f1 100644
--- a/distro/common/markdown/man1/knife-search.mkd
+++ b/distro/common/markdown/man1/knife-search.mkd
@@ -50,7 +50,7 @@ query syntax. The following data types are indexed for search:
Data bags are indexed by the data bag's name. For example, to search a
data bag named "admins":
- knife search admins "field:search_pattern"
+ knife search admins 'field:search_pattern'
## QUERY SYNTAX
@@ -95,7 +95,7 @@ within a search pattern.
Range searches allows one to match values between two given values. To
match values between X and Y, inclusively, use square brackets:
- knife search INDEX 'field:[X TO Y]
+ knife search INDEX 'field:[X TO Y]'
To match values between X and Y, exclusively, use curly brackets:
diff --git a/distro/powershell/chef/chef.psm1 b/distro/powershell/chef/chef.psm1
index 9196d62e6c..05fee05e5e 100644
--- a/distro/powershell/chef/chef.psm1
+++ b/distro/powershell/chef/chef.psm1
@@ -236,7 +236,6 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
throw "Unable to create process [$ArgumentString]. Error code $reason."
}
- $sb = New-Object System.Text.StringBuilder
$buffer = New-Object byte[] 1024
# Initialize reference variables
@@ -270,7 +269,7 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
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)
+ $output
}
if ($bytesRead -lt $buffer.Length) {
# Partial buffer indicating the end of stream, break out of ReadFile loop
@@ -282,6 +281,24 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
break
}
}
+ } else {
+ # For some reason, you can't read from the read-end of the read-pipe before the write end has started
+ # to write. Otherwise the process just blocks forever and never returns from the read. So we peek
+ # at the pipe until there is something. But don't peek too eagerly. This is stupid stupid stupid.
+ # There must be a way to do this without having to peek at a pipe first but I have not found it.
+ #
+ # Note to the future intrepid soul who wants to fix this:
+ # 0) This is related to unreasonable CPU usage by the wrapper PS script on a 1 VCPU VM (either Hyper-V
+ # or VirtualBox) running a consumer Windows SKU (Windows 10 for example...). Test it there.
+ # 1) Maybe this entire script is unnecessary and the bugs mentioned below have been fixed or don't need
+ # to be supported.
+ # 2) The server and consumer windows schedulers have different defaults. I had a hard time reproducing
+ # any issue on a win 2008 on win 2012 server default setup. See the "foreground application scheduler
+ # priority" setting to see if it's relevant.
+ # 3) This entire endeavor is silly anyway - why are we reimplementing process forking all over? Maybe try
+ # to get the folks above to accept patches instead of extending this crazy script.
+ Start-Sleep -s 1
+ # Start-Sleep -m 100
}
if ($global:LASTEXITCODE -ne [Chef.Kernel32]::STILL_ACTIVE) {
@@ -289,9 +306,6 @@ function Run-ExecutableAndWait($AppPath, $ArgumentString) {
}
}
- # Return output obtained from child process stdout/stderr
- $sb.ToString()
-
# Cleanup handles
$success = [Chef.Kernel32]::CloseHandle($pi.hProcess)
if (-Not $success) {
@@ -434,9 +448,12 @@ Export-ModuleMember -function chef-solo
Export-ModuleMember -function chef-windows-service
Export-ModuleMember -function knife
-# To debug this module, uncomment the line below and then run the following.
+# To debug this module, uncomment the line below
# Export-ModuleMember -function Run-RubyCommand
+
+# Then run the following to reload the module. Use puts_argv as a helpful debug executable.
# Remove-Module chef
# Import-Module chef
-# "puts ARGV" | Out-File C:\opscode\chef\bin\puts_args
+# "puts ARGV" | Out-File C:\opscode\chef\bin\puts_args -Encoding ASCII
+# Copy-Item C:\opscode\chef\bin\ohai.bat C:\opscode\chef\bin\puts_args.bat
# Run-RubyCommand puts_args 'Here' "are" some '"very interesting"' 'arguments[to]' "`"try out`""
diff --git a/kitchen-tests/.kitchen.travis.yml b/kitchen-tests/.kitchen.travis.yml
index 720f034cb5..a8bc149b94 100644
--- a/kitchen-tests/.kitchen.travis.yml
+++ b/kitchen-tests/.kitchen.travis.yml
@@ -29,14 +29,13 @@ verifier:
format: progress
platforms:
-- name: debian-7
+- name: amazonlinux
driver:
- image: dokken/debian-7
+ image: dokken/amazonlinux
pid_one_command: /sbin/init
intermediate_instructions:
- - RUN /usr/bin/apt-get update
- - RUN /usr/bin/apt-get -y install sudo
- - RUN /bin/mkdir /var/run/sshd
+ - RUN yum -y install sudo
+ - RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
- name: debian-8
driver:
@@ -57,13 +56,10 @@ platforms:
- name: centos-6
driver:
image: dokken/centos-6
- run_command: /sbin/init
+ pid_one_command: /sbin/init
intermediate_instructions:
- RUN yum -y install sudo
- RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
- attributes:
- chef_client:
- init_style: init
- name: centos-7
driver:
@@ -101,22 +97,18 @@ platforms:
driver:
image: dokken/opensuse-leap
pid_one_command: /bin/systemd
-
-- name: amazonlinux
- driver:
- image: dokken/amazonlinux
- pid_one_command: /sbin/init
intermediate_instructions:
- - RUN yum -y install sudo
- - RUN sed -i -e "s/Defaults.*requiretty.*/Defaults !requiretty/g" /etc/sudoers
+ - RUN /usr/bin/zypper install -y sudo
suites:
- name: base
run_list:
- recipe[base::default]
- name: awesome_customers_ubuntu
+ includes: [ubuntu-14.04, ubuntu-16.04]
run_list:
- recipe[awesome_customers_ubuntu_wrapper::default]
- name: awesome_customers_rhel
+ includes: [centos-6, centos-7]
run_list:
- recipe[awesome_customers_rhel_wrapper::default]
diff --git a/kitchen-tests/.kitchen.yml b/kitchen-tests/.kitchen.yml
index 4e570b125e..b449265ce7 100644
--- a/kitchen-tests/.kitchen.yml
+++ b/kitchen-tests/.kitchen.yml
@@ -17,23 +17,30 @@ provisioner:
github_repo: "chef"
ohai_refname: "master"
refname: <%= %x(git rev-parse HEAD) %>
- data_path: test/fixtures
client_rb:
diff_disabled: true
platforms:
+ - name: amazonlinux
+ driver_config:
+ box: mvbcoding/awslinux
+ - name: centos-6
+ - name: centos-7
+ - name: debian-8
+ - name: debian-9
+ - name: opensuse-leap-42
- name: ubuntu-14.04
- name: ubuntu-16.04
- - name: centos-7
- - name: centos-6
suites:
- name: base
run_list:
- recipe[base::default]
- name: awesome_customers_ubuntu
+ includes: [ubuntu-14.04, ubuntu-16.04]
run_list:
- recipe[awesome_customers_ubuntu_wrapper::default]
- name: awesome_customers_rhel
+ includes: [centos-6, centos-7]
run_list:
- recipe[awesome_customers_rhel_wrapper::default]
diff --git a/kitchen-tests/Berksfile.lock b/kitchen-tests/Berksfile.lock
deleted file mode 100644
index 6cd1308fcd..0000000000
--- a/kitchen-tests/Berksfile.lock
+++ /dev/null
@@ -1,53 +0,0 @@
-DEPENDENCIES
- base
- path: cookbooks/base
-
-GRAPH
- apt (6.1.4)
- base (0.1.0)
- apt (>= 0.0.0)
- build-essential (>= 0.0.0)
- chef-client (>= 0.0.0)
- chef_hostname (>= 0.0.0)
- logrotate (>= 0.0.0)
- multipackage (>= 0.0.0)
- nscd (>= 0.0.0)
- ntp (>= 0.0.0)
- openssh (>= 0.0.0)
- resolver (>= 0.0.0)
- selinux (>= 0.0.0)
- sudo (>= 0.0.0)
- ubuntu (>= 0.0.0)
- users (>= 0.0.0)
- build-essential (8.0.3)
- mingw (>= 1.1)
- seven_zip (>= 0.0.0)
- chef-client (8.1.8)
- cron (>= 2.0.0)
- logrotate (>= 1.9.0)
- windows (>= 2.0.0)
- chef_hostname (0.6.1)
- compat_resource (12.19.0)
- cron (4.1.3)
- compat_resource (>= 0.0.0)
- iptables (4.2.1)
- logrotate (2.2.0)
- mingw (2.0.1)
- seven_zip (>= 0.0.0)
- multipackage (4.0.0)
- compat_resource (>= 0.0.0)
- nscd (5.0.0)
- ntp (3.5.2)
- ohai (5.2.0)
- openssh (2.5.0)
- iptables (>= 1.0)
- resolver (2.0.1)
- selinux (2.1.0)
- seven_zip (2.0.2)
- windows (>= 1.2.2)
- sudo (3.5.3)
- ubuntu (2.0.1)
- apt (>= 0.0.0)
- users (5.1.0)
- windows (3.1.2)
- ohai (>= 4.0.0)
diff --git a/kitchen-tests/Gemfile b/kitchen-tests/Gemfile
index e41d2ff808..9cc63fb7d6 100644
--- a/kitchen-tests/Gemfile
+++ b/kitchen-tests/Gemfile
@@ -1,13 +1,12 @@
source "https://rubygems.org"
-gem "chef-config", "< 13"
gem "rake" # required to build some native extensions
-gem "berkshelf"
-gem "kitchen-appbundle-updater"
+gem "chef", path: ".."
+# remove this ohai pin once we ship the 14 gem
+gem "ohai", git: "https://github.com/chef/ohai.git", branch: "master"
+gem "berkshelf", git: "https://github.com/berkshelf/berkshelf.git", branch: "master"
+gem "kitchen-appbundle-updater", git: "https://github.com/chef/kitchen-appbundle-updater", branch: "master"
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"
-gem "ridley"
-gem "test-kitchen"
-gem "vagrant-wrapper"
+gem "kitchen-inspec", git: "https://github.com/chef/kitchen-inspec.git", branch: "master"
+gem "kitchen-vagrant", git: "https://github.com/test-kitchen/kitchen-vagrant.git", branch: "master"
+gem "test-kitchen", git: "https://github.com/test-kitchen/test-kitchen.git", branch: "master"
diff --git a/kitchen-tests/Gemfile.lock b/kitchen-tests/Gemfile.lock
deleted file mode 100644
index 8881c6b839..0000000000
--- a/kitchen-tests/Gemfile.lock
+++ /dev/null
@@ -1,269 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- addressable (2.5.1)
- public_suffix (~> 2.0, >= 2.0.2)
- artifactory (2.8.1)
- aws-sdk (2.9.1)
- aws-sdk-resources (= 2.9.1)
- aws-sdk-core (2.9.1)
- aws-sigv4 (~> 1.0)
- jmespath (~> 1.0)
- aws-sdk-resources (2.9.1)
- aws-sdk-core (= 2.9.1)
- aws-sigv4 (1.0.0)
- berkshelf (5.6.4)
- addressable (~> 2.3, >= 2.3.4)
- 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.4)
- octokit (~> 4.0)
- retryable (~> 2.0)
- 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)
- blankslate (2.1.2.4)
- 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.19.36)
- addressable
- fuzzyurl
- mixlib-config (~> 2.0)
- mixlib-shellout (~> 2.0)
- cleanroom (1.0.0)
- coderay (1.1.1)
- diff-lcs (1.3)
- docker-api (1.33.2)
- excon (>= 0.38.0)
- json
- erubis (2.7.0)
- excon (0.55.0)
- faraday (0.9.2)
- multipart-post (>= 1.2, < 3)
- ffi (1.9.18)
- ffi (1.9.18-x86-mingw32)
- fuzzyurl (0.9.0)
- gssapi (1.2.0)
- ffi (>= 1.0.1)
- gyoku (1.3.1)
- builder (>= 2.1.2)
- hashie (3.5.5)
- hitimes (1.2.4)
- hitimes (1.2.4-x86-mingw32)
- httpclient (2.8.3)
- inspec (1.18.0)
- addressable (~> 2.5)
- faraday (>= 0.9.0)
- hashie (~> 3.4)
- json (>= 1.8, < 3.0)
- method_source (~> 0.8)
- mixlib-log
- nokogiri (~> 1.6)
- parallel (~> 1.9)
- pry (~> 0)
- rainbow (~> 2)
- rspec (~> 3)
- rspec-its (~> 1.2)
- rubyzip (~> 1.1)
- sslshake (~> 1)
- thor (~> 0.19)
- toml (~> 0.1)
- train (>= 0.22.0, < 1.0)
- jmespath (1.3.1)
- json (2.0.3)
- kitchen-appbundle-updater (0.2.0)
- kitchen-dokken (1.1.0)
- docker-api (~> 1.33)
- test-kitchen (~> 1.13)
- kitchen-ec2 (1.3.2)
- aws-sdk (~> 2)
- excon
- multi_json
- retryable (~> 2.0)
- test-kitchen (~> 1.4, >= 1.4.1)
- kitchen-inspec (0.17.0)
- hashie (~> 3.4)
- inspec (>= 0.34.0, < 2.0.0)
- test-kitchen (~> 1.6)
- kitchen-vagrant (1.0.2)
- test-kitchen (~> 1.4)
- little-plugger (1.1.4)
- logging (2.2.0)
- little-plugger (~> 1.1)
- multi_json (~> 1.10)
- method_source (0.8.2)
- mini_portile (0.6.2)
- 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.12)
- artifactory
- mixlib-shellout
- mixlib-versioning
- thor
- mixlib-log (1.7.1)
- mixlib-shellout (2.2.7)
- mixlib-shellout (2.2.7-universal-mingw32)
- win32-process (~> 0.8.2)
- wmi-lite (~> 1.0)
- mixlib-versioning (1.1.0)
- molinillo (0.5.7)
- multi_json (1.12.1)
- multipart-post (2.0.0)
- net-scp (1.2.1)
- net-ssh (>= 2.6.5)
- net-ssh (4.1.0)
- net-ssh-gateway (1.3.0)
- net-ssh (>= 2.6.5)
- nio4r (2.0.0)
- nokogiri (1.6.6.4)
- mini_portile (~> 0.6.0)
- nokogiri (1.6.6.4-x86-mingw32)
- mini_portile (~> 0.6.0)
- nori (2.6.0)
- octokit (4.6.2)
- sawyer (~> 0.8.0, >= 0.5.3)
- parallel (1.11.1)
- parslet (1.5.0)
- blankslate (~> 2.0)
- pry (0.10.4)
- coderay (~> 1.1.0)
- method_source (~> 0.8.1)
- slop (~> 3.4)
- public_suffix (2.0.5)
- rainbow (2.2.1)
- rake (12.0.0)
- retryable (2.0.4)
- ridley (5.1.0)
- addressable
- 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)
- erubis
- faraday (~> 0.9.0)
- hashie (>= 2.0.2, < 4.0.0)
- httpclient (~> 2.7)
- json (>= 1.7.7)
- mixlib-authentication (>= 1.3.0)
- retryable (~> 2.0)
- semverse (~> 2.0)
- varia_model (~> 0.6)
- rspec (3.5.0)
- rspec-core (~> 3.5.0)
- rspec-expectations (~> 3.5.0)
- rspec-mocks (~> 3.5.0)
- rspec-core (3.5.4)
- rspec-support (~> 3.5.0)
- rspec-expectations (3.5.0)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.5.0)
- rspec-its (1.2.0)
- rspec-core (>= 3.0.0)
- rspec-expectations (>= 3.0.0)
- rspec-mocks (3.5.0)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.5.0)
- rspec-support (3.5.0)
- rubyntlm (0.6.1)
- rubyzip (1.2.1)
- safe_yaml (1.0.4)
- 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.1.0)
- molinillo (>= 0.5)
- semverse (>= 1.1, < 3.0)
- sslshake (1.1.0)
- test-kitchen (1.16.0)
- mixlib-install (>= 1.2, < 3.0)
- mixlib-shellout (>= 1.2, < 3.0)
- net-scp (~> 1.1)
- net-ssh (>= 2.9, < 5.0)
- net-ssh-gateway (~> 1.2)
- safe_yaml (~> 1.0)
- thor (~> 0.19, < 0.19.2)
- thor (0.19.1)
- timers (4.0.4)
- hitimes
- toml (0.1.2)
- parslet (~> 1.5.0)
- train (0.23.0)
- docker-api (~> 1.26)
- json (>= 1.8, < 3.0)
- mixlib-shellout (~> 2.0)
- net-scp (~> 1.2)
- net-ssh (>= 2.9, < 5.0)
- winrm (~> 2.0)
- winrm-fs (~> 1.0)
- vagrant-wrapper (2.0.3)
- varia_model (0.6.0)
- buff-extensions (~> 2.0)
- hashie (>= 2.0.2, < 4.0.0)
- win32-process (0.8.3)
- ffi (>= 1.0.0)
- winrm (2.1.3)
- builder (>= 2.1.2)
- erubis (~> 2.7)
- gssapi (~> 1.2)
- gyoku (~> 1.0)
- httpclient (~> 2.2, >= 2.2.0.2)
- logging (>= 1.6.1, < 3.0)
- nori (~> 2.0)
- rubyntlm (~> 0.6.0, >= 0.6.1)
- 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)
-
-PLATFORMS
- ruby
- x86-mingw32
-
-DEPENDENCIES
- berkshelf
- chef-config (< 13)
- kitchen-appbundle-updater
- kitchen-dokken (< 2.0)
- kitchen-ec2
- kitchen-inspec
- kitchen-vagrant
- rake
- ridley
- test-kitchen
- vagrant-wrapper
-
-BUNDLED WITH
- 1.14.6
diff --git a/kitchen-tests/cookbooks/audit_test/.gitignore b/kitchen-tests/cookbooks/audit_test/.gitignore
deleted file mode 100644
index 1e074046f0..0000000000
--- a/kitchen-tests/cookbooks/audit_test/.gitignore
+++ /dev/null
@@ -1,15 +0,0 @@
-.vagrant
-*~
-*#
-.#*
-\#*#
-.*.sw[a-z]
-*.un~
-
-# Bundler
-Gemfile.lock
-bin/*
-.bundle/*
-
-.kitchen/
-.kitchen.local.yml
diff --git a/kitchen-tests/cookbooks/audit_test/chefignore b/kitchen-tests/cookbooks/audit_test/chefignore
deleted file mode 100644
index 80dc2d20ef..0000000000
--- a/kitchen-tests/cookbooks/audit_test/chefignore
+++ /dev/null
@@ -1,95 +0,0 @@
-# Put files/directories that should be ignored in this file when uploading
-# or sharing to the community site.
-# Lines that start with '# ' are comments.
-
-# OS generated files #
-######################
-.DS_Store
-Icon?
-nohup.out
-ehthumbs.db
-Thumbs.db
-
-# SASS #
-########
-.sass-cache
-
-# EDITORS #
-###########
-\#*
-.#*
-*~
-*.sw[a-z]
-*.bak
-REVISION
-TAGS*
-tmtags
-*_flymake.*
-*_flymake
-*.tmproj
-.project
-.settings
-mkmf.log
-
-## COMPILED ##
-##############
-a.out
-*.o
-*.pyc
-*.so
-*.com
-*.class
-*.dll
-*.exe
-*/rdoc/
-
-# Testing #
-###########
-.watchr
-.rspec
-spec/*
-spec/fixtures/*
-test/*
-features/*
-Guardfile
-Procfile
-
-# SCM #
-#######
-.git
-*/.git
-.gitignore
-.gitmodules
-.gitconfig
-.gitattributes
-.svn
-*/.bzr/*
-*/.hg/*
-*/.svn/*
-
-# Berkshelf #
-#############
-Berksfile
-Berksfile.lock
-cookbooks/*
-tmp
-
-# Cookbooks #
-#############
-CONTRIBUTING
-
-# Strainer #
-############
-Colanderfile
-Strainerfile
-.colander
-.strainer
-
-# Vagrant #
-###########
-.vagrant
-Vagrantfile
-
-# Travis #
-##########
-.travis.yml
diff --git a/kitchen-tests/cookbooks/base/attributes/default.rb b/kitchen-tests/cookbooks/base/attributes/default.rb
index 75e57cb27b..c952f0887e 100644
--- a/kitchen-tests/cookbooks/base/attributes/default.rb
+++ b/kitchen-tests/cookbooks/base/attributes/default.rb
@@ -27,7 +27,7 @@ default["openssh"]["client"]["strict_host_key_checking"] = "no"
default["openssh"]["client"]["protocol"] = "2"
# it is mostly important that the aes*-ctr ciphers appear first in this list, the cbc ciphers are for compatibility
-default["openssh"]["server"]["ciphers"] = "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,blowfish-cbc,3des-cbc,cast128-cbc"
+default["openssh"]["server"]["ciphers"] = "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-cbc"
# DNS causes long timeouts when connecting clients have busted DNS
default["openssh"]["server"]["use_dns"] = "no"
default["openssh"]["server"]["syslog_facility"] = "AUTH"
@@ -43,7 +43,6 @@ default["openssh"]["server"]["challenge_response_authentication"] = "no"
default["openssh"]["server"]["kerberos_authentication"] = "no"
# tcp keepalives are useful to keep connections up through VPNs and firewalls
default["openssh"]["server"]["tcp_keepalive"] = "yes"
-default["openssh"]["server"]["use_privilege_separation"] = "yes"
default["openssh"]["server"]["max_start_ups"] = "10"
# PAM (i think) already prints the motd on login
default["openssh"]["server"]["print_motd"] = "no"
@@ -75,6 +74,7 @@ default["resolver"]["search"] = "chef.io"
#
default["authorization"]["sudo"]["passwordless"] = true
+default["authorization"]["sudo"]["groups"] = %w{sysadmin}
default["authorization"]["sudo"]["users"] = %w{vagrant centos ubuntu}
#
diff --git a/kitchen-tests/cookbooks/base/metadata.rb b/kitchen-tests/cookbooks/base/metadata.rb
index 9a85a0e24b..9d4e663bec 100644
--- a/kitchen-tests/cookbooks/base/metadata.rb
+++ b/kitchen-tests/cookbooks/base/metadata.rb
@@ -10,7 +10,9 @@ gem "chef-sugar"
depends "apt"
depends "build-essential"
+depends "chef-apt-docker"
depends "chef-client"
+depends "chef-yum-docker"
depends "chef_hostname"
depends "logrotate"
depends "multipackage"
@@ -22,6 +24,8 @@ depends "selinux"
depends "sudo"
depends "ubuntu"
depends "users"
+depends "cron"
+depends "git"
supports "ubuntu"
supports "debian"
diff --git a/kitchen-tests/cookbooks/base/recipes/default.rb b/kitchen-tests/cookbooks/base/recipes/default.rb
index bc98981d5d..e2d92cadc4 100644
--- a/kitchen-tests/cookbooks/base/recipes/default.rb
+++ b/kitchen-tests/cookbooks/base/recipes/default.rb
@@ -7,10 +7,9 @@
hostname "chef-travis-ci.chef.io"
-if platform_family?("debian")
- include_recipe "ubuntu"
- apt_update
-end
+apt_update
+
+include_recipe "ubuntu" if platform?("ubuntu")
if platform_family?("rhel", "fedora", "amazon")
include_recipe "selinux::disabled"
@@ -45,8 +44,8 @@ include_recipe "chef-client::delete_validation"
include_recipe "chef-client::config"
include_recipe "chef-client"
-# hack needed for debian-7 on docker
-directory "/var/run/sshd"
+include_recipe "chef-apt-docker"
+include_recipe "chef-yum-docker"
include_recipe "openssh"
@@ -54,4 +53,28 @@ include_recipe "nscd"
include_recipe "logrotate"
+include_recipe "cron"
+
+include_recipe "git"
+
+directory "/etc/ssl"
+
+# Generate new key and certificate
+openssl_dhparam "/etc/ssl/dhparam.pem" do
+ key_length 1024
+ action :create
+end
+
+# Generate new key with aes-128-cbc cipher
+openssl_rsa_private_key "/etc/ssl/rsakey_aes128cbc.pem" do
+ key_length 1024
+ key_cipher "aes-128-cbc"
+ action :create
+end
+
+openssl_rsa_public_key "/etc/ssl/rsakey_aes128cbc.pub" do
+ private_key_path "/etc/ssl/rsakey_aes128cbc.pem"
+ action :create
+end
+
include_recipe "::tests"
diff --git a/kitchen-tests/cookbooks/base/recipes/packages.rb b/kitchen-tests/cookbooks/base/recipes/packages.rb
index a448936acd..fc65a2d8f7 100644
--- a/kitchen-tests/cookbooks/base/recipes/packages.rb
+++ b/kitchen-tests/cookbooks/base/recipes/packages.rb
@@ -7,7 +7,7 @@
# 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 }
+pkgs = %w{lsof tcpdump strace zsh dmidecode ltrace bc curl wget subversion 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/lib/chef/api_client.rb b/lib/chef/api_client.rb
index 087de3fdf9..551d9a6035 100644
--- a/lib/chef/api_client.rb
+++ b/lib/chef/api_client.rb
@@ -47,7 +47,7 @@ class Chef
# Gets or sets the client name.
#
- # @params [Optional String] The name must be alpha-numeric plus - and _.
+ # @param [Optional String] The name must be alpha-numeric plus - and _.
# @return [String] The current value of the name.
def name(arg = nil)
set_or_return(
@@ -59,7 +59,7 @@ class Chef
# Gets or sets whether this client is an admin.
#
- # @params [Optional True/False] Should be true or false - default is false.
+ # @param [Optional True/False] Should be true or false - default is false.
# @return [True/False] The current value
def admin(arg = nil)
set_or_return(
@@ -71,7 +71,7 @@ class Chef
# Gets or sets the public key.
#
- # @params [Optional String] The string representation of the public key.
+ # @param [Optional String] The string representation of the public key.
# @return [String] The current value.
def public_key(arg = nil)
set_or_return(
@@ -83,7 +83,7 @@ class Chef
# Gets or sets whether this client is a validator.
#
- # @params [Boolean] whether or not the client is a validator. If
+ # @param [Boolean] whether or not the client is a validator. If
# `nil`, retrieves the already-set value.
# @return [Boolean] The current value
def validator(arg = nil)
@@ -96,7 +96,7 @@ class Chef
# Gets or sets the private key.
#
- # @params [Optional String] The string representation of the private key.
+ # @param [Optional String] The string representation of the private key.
# @return [String] The current value.
def private_key(arg = nil)
set_or_return(
diff --git a/lib/chef/api_client_v1.rb b/lib/chef/api_client_v1.rb
index a1b9b8317e..7fbff6d6ba 100644
--- a/lib/chef/api_client_v1.rb
+++ b/lib/chef/api_client_v1.rb
@@ -70,7 +70,7 @@ class Chef
# Gets or sets the client name.
#
- # @params [Optional String] The name must be alpha-numeric plus - and _.
+ # @param arg [Optional String] The name must be alpha-numeric plus - and _.
# @return [String] The current value of the name.
def name(arg = nil)
set_or_return(
@@ -82,7 +82,7 @@ class Chef
# Gets or sets whether this client is an admin.
#
- # @params [Optional True/False] Should be true or false - default is false.
+ # @param arg [Optional True/False] Should be true or false - default is false.
# @return [True/False] The current value
def admin(arg = nil)
set_or_return(
@@ -94,7 +94,7 @@ class Chef
# Gets or sets the public key.
#
- # @params [Optional String] The string representation of the public key.
+ # @param arg [Optional String] The string representation of the public key.
# @return [String] The current value.
def public_key(arg = nil)
set_or_return(
@@ -106,7 +106,7 @@ class Chef
# Gets or sets whether this client is a validator.
#
- # @params [Boolean] whether or not the client is a validator. If
+ # @param arg [Boolean] whether or not the client is a validator. If
# `nil`, retrieves the already-set value.
# @return [Boolean] The current value
def validator(arg = nil)
@@ -120,7 +120,7 @@ class Chef
# Private key. The server will return it as a string.
# Set to true under API V0 to have the server regenerate the default key.
#
- # @params [Optional String] The string representation of the private key.
+ # @param arg [Optional String] The string representation of the private key.
# @return [String] The current value.
def private_key(arg = nil)
set_or_return(
@@ -132,7 +132,7 @@ class Chef
# Used to ask server to generate key pair under api V1
#
- # @params [Optional True/False] Should be true or false - default is false.
+ # @param arg [Optional True/False] Should be true or false - default is false.
# @return [True/False] The current value
def create_key(arg = nil)
set_or_return(
@@ -200,6 +200,7 @@ class Chef
end
# Load a client by name via the API
+ # @param name [String] the client name
def self.load(name)
response = http_api.get("clients/#{name}")
Chef::ApiClientV1.from_hash(response)
diff --git a/lib/chef/application.rb b/lib/chef/application.rb
index 096ce9c392..b20766c8b5 100644
--- a/lib/chef/application.rb
+++ b/lib/chef/application.rb
@@ -1,7 +1,7 @@
#
# Author:: AJ Christensen (<aj@chef.io>)
# Author:: Mark Mzyk (mmzyk@chef.io)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -90,6 +90,7 @@ class Chef
load_config_file
Chef::Config.export_proxies
Chef::Config.init_openssl
+ File.umask Chef::Config[:umask]
end
# Parse the config file
@@ -176,7 +177,7 @@ class Chef
# Based on config and whether or not STDOUT is a tty, should we setup a
# secondary logger for stdout?
def want_additional_logger?
- ( Chef::Config[:log_location] != STDOUT ) && STDOUT.tty? && !Chef::Config[:daemonize]
+ !( Chef::Config[:log_location].is_a?(IO) && Chef::Config[:log_location].tty? ) && !Chef::Config[:daemonize]
end
def configure_stdout_logger
diff --git a/lib/chef/application/client.rb b/lib/chef/application/client.rb
index ae16777cb6..32530925d5 100644
--- a/lib/chef/application/client.rb
+++ b/lib/chef/application/client.rb
@@ -501,7 +501,7 @@ class Chef::Application::Client < Chef::Application
# we need to sleep again after reconfigure to avoid stampeding when logrotate runs out of cron
if signal == RECONFIGURE_SIGNAL
reconfigure
- interval_sleep(sleep)
+ interval_sleep(sec)
end
else
sleep(sec)
diff --git a/lib/chef/application/knife.rb b/lib/chef/application/knife.rb
index 6a09427ccd..c972e9313e 100644
--- a/lib/chef/application/knife.rb
+++ b/lib/chef/application/knife.rb
@@ -148,6 +148,10 @@ class Chef::Application::Knife < Chef::Application
:boolean => true,
:default => nil
+ option :profile,
+ :long => "--profile PROFILE",
+ :description => "The credentials profile to select"
+
# Run knife
def run
Mixlib::Log::Formatter.show_time = false
diff --git a/lib/chef/application/solo.rb b/lib/chef/application/solo.rb
index f246b1946a..6b4aef42b4 100644
--- a/lib/chef/application/solo.rb
+++ b/lib/chef/application/solo.rb
@@ -1,7 +1,7 @@
#
# Author:: AJ Christensen (<aj@chef.io>)
# Author:: Mark Mzyk (mmzyk@chef.io)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2018, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -238,17 +238,10 @@ class Chef::Application::Solo < Chef::Application
Chef::Config[:solo] = true
- Chef::Log.deprecation("-r MUST be changed to --recipe-url, the -r option will be changed in Chef 13.0") if ARGV.include?("-r")
-
if !Chef::Config[:solo_legacy_mode]
# Because we re-parse ARGV when we move to chef-client, we need to tidy up some options first.
ARGV.delete("--ez")
- # -r means something entirely different in chef-client land, so let's replace it with a "safe" value
- if dash_r = ARGV.index("-r")
- ARGV[dash_r] = "--recipe-url"
- end
-
# For back compat reasons, we need to ensure that we try and use the cache_path as a repo first
Chef::Log.debug "Current chef_repo_path is #{Chef::Config.chef_repo_path}"
diff --git a/lib/chef/audit/audit_reporter.rb b/lib/chef/audit/audit_reporter.rb
index 8546a21bb4..80ae3a8dd4 100644
--- a/lib/chef/audit/audit_reporter.rb
+++ b/lib/chef/audit/audit_reporter.rb
@@ -1,7 +1,7 @@
#
# Author:: Tyler Ball (<tball@chef.io>)
#
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -49,7 +49,7 @@ class Chef
def audit_phase_complete(audit_output)
Chef::Log.debug("Audit Reporter completed successfully without errors.")
- ordered_control_groups.each do |name, control_group|
+ ordered_control_groups.each_value do |control_group|
audit_data.add_control_group(control_group)
end
end
@@ -62,7 +62,7 @@ class Chef
# The stacktrace information has already been logged elsewhere
@audit_phase_error = error
Chef::Log.debug("Audit Reporter failed.")
- ordered_control_groups.each do |name, control_group|
+ ordered_control_groups.each_value do |control_group|
audit_data.add_control_group(control_group)
end
end
diff --git a/lib/chef/audit/runner.rb b/lib/chef/audit/runner.rb
index 837346381c..f6fed3fc64 100644
--- a/lib/chef/audit/runner.rb
+++ b/lib/chef/audit/runner.rb
@@ -1,6 +1,6 @@
#
# Author:: Claire McQuin (<claire@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -163,7 +163,7 @@ class Chef
# or use example group filters.
def register_control_groups
add_example_group_methods
- run_context.audits.each do |name, group|
+ run_context.audits.each do |name, group| # rubocop:disable Performance/HashEachMethods
ctl_grp = RSpec::Core::ExampleGroup.__control_group__(*group.args, &group.block)
RSpec.world.record(ctl_grp)
end
diff --git a/lib/chef/chef_class.rb b/lib/chef/chef_class.rb
index e61fd5e1d2..bfea51609a 100644
--- a/lib/chef/chef_class.rb
+++ b/lib/chef/chef_class.rb
@@ -200,8 +200,8 @@ class Chef
#
# Emit a deprecation message.
#
- # @param type The message to send. This should be a symbol, referring to
- # a class defined in Chef::Deprecated
+ # @param [Symbol] type The message to send. This should refer 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
diff --git a/lib/chef/chef_fs/config.rb b/lib/chef/chef_fs/config.rb
index 63a1363724..0725426275 100644
--- a/lib/chef/chef_fs/config.rb
+++ b/lib/chef/chef_fs/config.rb
@@ -66,7 +66,7 @@ class Chef
# upgrade/migration of older Chef Servers, so they should be considered
# frozen in time.
- CHEF_11_OSS_STATIC_OBJECTS = %w{cookbooks cookbook_artifacts data_bags environments roles}.freeze
+ CHEF_11_OSS_STATIC_OBJECTS = %w{cookbooks data_bags environments roles}.freeze
CHEF_11_OSS_DYNAMIC_OBJECTS = %w{clients nodes users}.freeze
RBAC_OBJECT_NAMES = %w{acls containers groups }.freeze
CHEF_12_OBJECTS = %w{ cookbook_artifacts policies policy_groups client_keys }.freeze
diff --git a/lib/chef/chef_fs/data_handler/acl_data_handler.rb b/lib/chef/chef_fs/data_handler/acl_data_handler.rb
index 6c8833004a..834fc5ca0b 100644
--- a/lib/chef/chef_fs/data_handler/acl_data_handler.rb
+++ b/lib/chef/chef_fs/data_handler/acl_data_handler.rb
@@ -13,7 +13,7 @@ class Chef
"delete" => {},
"grant" => {},
})
- result.keys.each do |key|
+ result.each_key do |key|
result[key] = normalize_hash(result[key], { "actors" => [], "groups" => [] })
result[key]["actors"] = result[key]["actors"].sort
result[key]["groups"] = result[key]["groups"].sort
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 e799e72e36..3b1fb53da6 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
@@ -5,6 +5,8 @@ class Chef
module ChefFS
module DataHandler
class DataBagItemDataHandler < DataHandlerBase
+ RESERVED_NAMES = /^(node|role|environment|client)$/
+
def normalize(data_bag_item, entry)
# If it's wrapped with raw_data, unwrap it.
if data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
@@ -43,6 +45,7 @@ class Chef
end
# Verify that the JSON hash for this type has a key that matches its name.
+ # Also check that the data bag name is not a reserved search index name.
#
# @param object [Object] JSON hash of the object
# @param entry [Chef::ChefFS::FileSystem::BaseFSObject] filesystem object we are verifying
@@ -52,6 +55,8 @@ class Chef
base_name = remove_dot_json(entry.name)
if object["raw_data"]["id"] != base_name
yield("ID in #{entry.path_for_printing} must be '#{base_name}' (is '#{object['raw_data']['id']}')")
+ elsif entry.parent.name =~ RESERVED_NAMES
+ yield("Data bag name ('#{entry.parent.name}') must not match #{RESERVED_NAMES.inspect}")
end
end
diff --git a/lib/chef/chef_fs/data_handler/data_handler_base.rb b/lib/chef/chef_fs/data_handler/data_handler_base.rb
index 3668f77dd5..4b4696ce5e 100644
--- a/lib/chef/chef_fs/data_handler/data_handler_base.rb
+++ b/lib/chef/chef_fs/data_handler/data_handler_base.rb
@@ -56,8 +56,7 @@ class Chef
# 2. Put the actual values in the order of the defaults
# 3. Move any other values to the end
#
- # == Example
- #
+ # @example
# normalize_hash({x: 100, c: 2, a: 1}, { a: 10, b: 20, c: 30})
# -> { a: 1, b: 20, c: 2, x: 100}
#
@@ -140,8 +139,7 @@ class Chef
# the keys specified in "keys"; anything else must be emitted by the
# caller.
#
- # == Example
- #
+ # @example
# to_ruby_keys({"name" => "foo", "environment" => "desert", "foo": "bar"}, [ "name", "environment" ])
# ->
# 'name "foo"
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 64488ed705..9b0ea18cd8 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
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -76,7 +76,7 @@ class Chef
if @children.nil?
@children = []
manifest = chef_object.cookbook_manifest
- manifest.by_parent_directory.each do |segment, files|
+ manifest.by_parent_directory.each_value do |files|
files.each do |file|
parts = file[:path].split("/")
# Get or create the path to the file
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 a4add1378d..8259db473d 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
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -71,7 +71,7 @@ class Chef
result = []
data = root.get_json(api_path)
data.keys.sort.each do |policy_name|
- data[policy_name]["revisions"].keys.each do |policy_revision|
+ data[policy_name]["revisions"].each_key do |policy_revision|
filename = "#{policy_name}-#{policy_revision}.json"
result << make_child_entry(filename, true)
end
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index 9f8a34e85e..6ff2d78ee6 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -3,7 +3,7 @@
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Christopher Brown (<cb@chef.io>)
# Author:: Tim Hinderliter (<tim@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -100,14 +100,6 @@ class Chef
attr_reader :rest
#
- # A rest object with validate_utf8 set to false. This will not throw exceptions
- # on non-UTF8 strings in JSON but will sanitize them so that e.g. POSTs will
- # never fail. Cannot be configured on a request-by-request basis, so we carry
- # around another rest object for it.
- #
- attr_reader :rest_clean
-
- #
# The runner used to converge.
#
# @return [Chef::Runner]
@@ -299,7 +291,7 @@ class Chef
run_status.stop_clock
Chef::Log.info("Chef Run complete in #{run_status.elapsed_time} seconds")
run_completed_successfully
- events.run_completed(node)
+ events.run_completed(node, run_status)
# keep this inside the main loop to get exception backtraces
end_profiling
@@ -315,7 +307,7 @@ class Chef
run_status.exception = run_error
run_failed
end
- events.run_failed(run_error)
+ events.run_failed(run_error, run_status)
ensure
Chef::RequestID.instance.reset_request_id
@run_status = nil
@@ -398,8 +390,10 @@ class Chef
end
end
- # Rest client for use by API reporters. This rest client will not fail with an exception if
- # it is fed non-UTF8 data.
+ # A rest object with validate_utf8 set to false. This will not throw exceptions
+ # on non-UTF8 strings in JSON but will sanitize them so that e.g. POSTs will
+ # never fail. Cannot be configured on a request-by-request basis, so we carry
+ # around another rest object for it.
#
# @api private
def rest_clean(client_name = node_name, config = Chef::Config)
@@ -602,9 +596,12 @@ class Chef
# @api private
#
def run_ohai
- filter = Chef::Config[:minimal_ohai] ? %w{fqdn machinename hostname platform platform_version os os_version} : nil
+ filter = Chef::Config[:minimal_ohai] ? %w{fqdn machinename hostname platform platform_version ohai_time os os_version} : nil
ohai.all_plugins(filter)
events.ohai_completed(node)
+ rescue Ohai::Exceptions::CriticalPluginFailure => e
+ Chef::Log.error("Critical Ohai plugins failed: #{e.message}")
+ exit(false)
end
#
diff --git a/lib/chef/cookbook/chefignore.rb b/lib/chef/cookbook/chefignore.rb
index dce58ecdb8..a27af68cb0 100644
--- a/lib/chef/cookbook/chefignore.rb
+++ b/lib/chef/cookbook/chefignore.rb
@@ -33,12 +33,16 @@ class Chef
@ignores = parse_ignore_file
end
+ # @param [Array] list the list of cookbook files
+ # @return [Array] list of cookbook files with chefignore files removed
def remove_ignores_from(file_list)
Array(file_list).inject([]) do |unignored, file|
ignored?(file) ? unignored : unignored << file
end
end
+ # @param [String] file_name the file name to check ignored status for
+ # @return [Boolean] is the file ignored or not
def ignored?(file_name)
@ignores.any? { |glob| File.fnmatch?(glob, file_name) }
end
diff --git a/lib/chef/cookbook/cookbook_collection.rb b/lib/chef/cookbook/cookbook_collection.rb
index d06b8fd042..b2a4d5884a 100644
--- a/lib/chef/cookbook/cookbook_collection.rb
+++ b/lib/chef/cookbook/cookbook_collection.rb
@@ -1,7 +1,7 @@
#--
# Author:: Tim Hinderliter (<tim@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2010-2016 Chef Software, Inc.
+# Copyright:: Copyright 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,10 +47,10 @@ class Chef
# Currently checks chef_version and ohai_version in the cookbook metadata
# against the running Chef::VERSION and Ohai::VERSION.
#
- # @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the Chef::VERSION fails validation
- # @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the Ohai::VERSION fails validation
+ # @raise [Chef::Exceptions::CookbookChefVersionMismatch] if the Chef::VERSION fails validation
+ # @raise [Chef::Exceptions::CookbookOhaiVersionMismatch] if the Ohai::VERSION fails validation
def validate!
- each do |cookbook_name, cookbook_version|
+ each_value do |cookbook_version|
cookbook_version.metadata.validate_chef_version!
cookbook_version.metadata.validate_ohai_version!
end
diff --git a/lib/chef/cookbook/cookbook_version_loader.rb b/lib/chef/cookbook/cookbook_version_loader.rb
index 35dac27fa5..b139a8d489 100644
--- a/lib/chef/cookbook/cookbook_version_loader.rb
+++ b/lib/chef/cookbook/cookbook_version_loader.rb
@@ -13,7 +13,6 @@ class Chef
attr_reader :cookbook_settings
attr_reader :cookbook_paths
- attr_reader :metadata_filenames
attr_reader :frozen
attr_reader :uploaded_cookbook_version_file
diff --git a/lib/chef/cookbook/gem_installer.rb b/lib/chef/cookbook/gem_installer.rb
index 5b1426e4e8..0b64d3354f 100644
--- a/lib/chef/cookbook/gem_installer.rb
+++ b/lib/chef/cookbook/gem_installer.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright (c) 2010-2017, Chef Software Inc.
+# Copyright:: Copyright (c) 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,7 +38,7 @@ class Chef
def install
cookbook_gems = Hash.new { |h, k| h[k] = [] }
- cookbook_collection.each do |cookbook_name, cookbook_version|
+ cookbook_collection.each_value do |cookbook_version|
cookbook_version.metadata.gems.each do |args|
cookbook_gems[args.first] += args[1..-1]
end
diff --git a/lib/chef/cookbook/metadata.rb b/lib/chef/cookbook/metadata.rb
index b23c01e622..22f006640d 100644
--- a/lib/chef/cookbook/metadata.rb
+++ b/lib/chef/cookbook/metadata.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: AJ Christensen (<aj@chef.io>)
# Author:: Seth Falcon (<seth@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -74,7 +74,6 @@ class Chef
attr_reader :providing
attr_reader :attributes
attr_reader :recipes
- attr_reader :version
# @return [Array<Gem::Dependency>] Array of supported Chef versions
attr_reader :chef_versions
@@ -596,7 +595,7 @@ class Chef
# Validates that the Ohai::VERSION of the running chef-client matches one of the
# configured ohai_version statements in this cookbooks metadata.
#
- # @raises [Chef::Exceptions::CookbookOhaiVersionMismatch] if the cookbook fails validation
+ # @raise [Chef::Exceptions::CookbookOhaiVersionMismatch] if the cookbook fails validation
def validate_ohai_version!
unless gem_dep_matches?("ohai", Gem::Version.new(Ohai::VERSION), *ohai_versions)
raise Exceptions::CookbookOhaiVersionMismatch.new(Ohai::VERSION, name, version, *ohai_versions)
@@ -606,7 +605,7 @@ class Chef
# Validates that the Chef::VERSION of the running chef-client matches one of the
# configured chef_version statements in this cookbooks metadata.
#
- # @raises [Chef::Exceptions::CookbookChefVersionMismatch] if the cookbook fails validation
+ # @raise [Chef::Exceptions::CookbookChefVersionMismatch] if the cookbook fails validation
def validate_chef_version!
unless gem_dep_matches?("chef", Gem::Version.new(Chef::VERSION), *chef_versions)
raise Exceptions::CookbookChefVersionMismatch.new(Chef::VERSION, name, version, *chef_versions)
diff --git a/lib/chef/cookbook/synchronizer.rb b/lib/chef/cookbook/synchronizer.rb
index ed6b1d9700..991e418f99 100644
--- a/lib/chef/cookbook/synchronizer.rb
+++ b/lib/chef/cookbook/synchronizer.rb
@@ -154,6 +154,7 @@ class Chef
queue = Chef::Util::ThreadedJobQueue.new
+ Chef::Log.warn("skipping cookbook synchronization! DO NOT LEAVE THIS ENABLED IN PRODUCTION!!!") if Chef::Config[:skip_cookbook_sync]
files.each do |file|
queue << lambda do |lock|
full_file_path = sync_file(file)
@@ -279,10 +280,7 @@ class Chef
end
def cached_copy_up_to_date?(local_path, expected_checksum)
- if Chef::Config[:skip_cookbook_sync]
- Chef::Log.warn "skipping cookbook synchronization! DO NOT LEAVE THIS ENABLED IN PRODUCTION!!!"
- return true
- end
+ return true if Chef::Config[:skip_cookbook_sync]
if cache.has_key?(local_path)
current_checksum = CookbookVersion.checksum_cookbook_file(cache.load(local_path, false))
expected_checksum == current_checksum
diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb
index a965b43c61..1cd498496a 100644
--- a/lib/chef/cookbook_loader.rb
+++ b/lib/chef/cookbook_loader.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# Copyright:: Copyright 2009-2016, Daniel DeLeo
# License:: Apache License, Version 2.0
#
@@ -78,7 +78,7 @@ class Chef
# @api private
def load_cookbooks_without_shadow_warning
preload_cookbooks
- @loaders_by_name.each do |cookbook_name, _loaders|
+ @loaders_by_name.each_key do |cookbook_name|
load_cookbook(cookbook_name)
end
@cookbooks_by_name
@@ -142,6 +142,14 @@ class Chef
end
end
+ def each_key(&block)
+ cookbook_names.each(&block)
+ end
+
+ def each_value(&block)
+ values.each(&block)
+ end
+
def cookbook_names
@cookbooks_by_name.keys.sort
end
diff --git a/lib/chef/cookbook_uploader.rb b/lib/chef/cookbook_uploader.rb
index 5e11314190..470d7be5b6 100644
--- a/lib/chef/cookbook_uploader.rb
+++ b/lib/chef/cookbook_uploader.rb
@@ -145,7 +145,6 @@ class Chef
Chef::Log.info("Validating templates")
exit(1) unless syntax_checker.validate_templates
Chef::Log.info("Syntax OK")
- true
end
end
diff --git a/lib/chef/cookbook_version.rb b/lib/chef/cookbook_version.rb
index dcb8c97548..99438ade82 100644
--- a/lib/chef/cookbook_version.rb
+++ b/lib/chef/cookbook_version.rb
@@ -4,7 +4,7 @@
# Author:: Tim Hinderliter (<tim@chef.io>)
# Author:: Seth Falcon (<seth@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -54,11 +54,6 @@ class Chef
# CookbookVersion.
attr_reader :metadata
- attr_reader :recipe_filenames_by_name
- attr_reader :attribute_filenames_by_short_filename
-
- attr_accessor :chef_server_rest
-
# The `identifier` field is used for cookbook_artifacts, which are
# organized on the chef server according to their content. If the
# policy_mode option to CookbookManifest is set to true it will include
@@ -157,7 +152,6 @@ class Chef
def metadata=(metadata)
@metadata = metadata
@metadata.recipes_from_cookbook_version(self)
- @metadata
end
def manifest
diff --git a/lib/chef/data_bag.rb b/lib/chef/data_bag.rb
index 15531d7304..c5e2b38c94 100644
--- a/lib/chef/data_bag.rb
+++ b/lib/chef/data_bag.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Nuo Yan (<nuo@chef.io>)
# Author:: Christopher Brown (<cb@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,13 +33,15 @@ class Chef
include Chef::Mixin::ParamsValidate
VALID_NAME = /^[\.\-[:alnum:]_]+$/
-
- attr_accessor :chef_server_rest
+ RESERVED_NAMES = /^(node|role|environment|client)$/
def self.validate_name!(name)
unless name =~ VALID_NAME
raise Exceptions::InvalidDataBagName, "DataBags must have a name matching #{VALID_NAME.inspect}, you gave #{name.inspect}"
end
+ if name =~ RESERVED_NAMES
+ raise Exceptions::InvalidDataBagName, "DataBags may not have a name matching #{RESERVED_NAMES.inspect}, you gave #{name.inspect}"
+ end
end
# Create a new Chef::DataBag
diff --git a/lib/chef/data_bag_item.rb b/lib/chef/data_bag_item.rb
index d0fca26125..388da78dad 100644
--- a/lib/chef/data_bag_item.rb
+++ b/lib/chef/data_bag_item.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Nuo Yan (<nuo@chef.io>)
# Author:: Christopher Brown (<cb@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software, Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,8 +38,6 @@ class Chef
VALID_ID = /^[\.\-[:alnum:]_]+$/
- attr_accessor :chef_server_rest
-
def self.validate_id!(id_str)
if id_str.nil? || ( id_str !~ VALID_ID )
raise Exceptions::InvalidDataBagItemID, "Data Bag items must have an id matching #{VALID_ID.inspect}, you gave: #{id_str.inspect}"
@@ -66,10 +64,6 @@ class Chef
Chef::ServerAPI.new(Chef::Config[:chef_server_url])
end
- def raw_data
- @raw_data
- end
-
def validate_id!(id_str)
self.class.validate_id!(id_str)
end
diff --git a/lib/chef/data_collector/messages.rb b/lib/chef/data_collector/messages.rb
index ca854957d1..b4e30e8b5a 100644
--- a/lib/chef/data_collector/messages.rb
+++ b/lib/chef/data_collector/messages.rb
@@ -36,7 +36,7 @@ class Chef
#
def self.run_start_message(run_status)
{
- "chef_server_fqdn" => chef_server_fqdn(run_status),
+ "chef_server_fqdn" => chef_server_fqdn,
"entity_uuid" => node_uuid,
"id" => run_status.run_id,
"message_version" => "1.0.0",
@@ -61,7 +61,7 @@ class Chef
run_status = reporter_data[:run_status]
message = {
- "chef_server_fqdn" => chef_server_fqdn(run_status),
+ "chef_server_fqdn" => chef_server_fqdn,
"entity_uuid" => node_uuid,
"expanded_run_list" => reporter_data[:expanded_run_list],
"id" => run_status.run_id,
diff --git a/lib/chef/data_collector/messages/helpers.rb b/lib/chef/data_collector/messages/helpers.rb
index f42ddaaa4e..d9a3394265 100644
--- a/lib/chef/data_collector/messages/helpers.rb
+++ b/lib/chef/data_collector/messages/helpers.rb
@@ -31,7 +31,7 @@ class Chef
#
# @return [String] FQDN of the configured Chef Server, or node/localhost if not found.
#
- def chef_server_fqdn(run_status)
+ def chef_server_fqdn
if !Chef::Config[:chef_server_url].nil?
URI(Chef::Config[:chef_server_url]).host
elsif !Chef::Config[:node_name].nil?
diff --git a/lib/chef/deprecated.rb b/lib/chef/deprecated.rb
index 2cf0f3d1bc..ac4440f6db 100644
--- a/lib/chef/deprecated.rb
+++ b/lib/chef/deprecated.rb
@@ -258,6 +258,26 @@ class Chef
end
end
+ class DeployResource < Base
+ def id
+ 21
+ end
+
+ def target
+ "deploy_resource.html"
+ end
+ end
+
+ class ErlResource < Base
+ def id
+ 22
+ end
+
+ def target
+ "erl_resource.html"
+ end
+ end
+
# id 3694 was deleted
class Generic < Base
diff --git a/lib/chef/dsl/data_query.rb b/lib/chef/dsl/data_query.rb
index b966885724..8ec466ea35 100644
--- a/lib/chef/dsl/data_query.rb
+++ b/lib/chef/dsl/data_query.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -83,7 +83,3 @@ class Chef
end
end
end
-
-# **DEPRECATED**
-# This used to be part of chef/mixin/language. Load the file to activate the deprecation code.
-require "chef/mixin/language"
diff --git a/lib/chef/dsl/include_attribute.rb b/lib/chef/dsl/include_attribute.rb
index 6d27fefc25..9f73143722 100644
--- a/lib/chef/dsl/include_attribute.rb
+++ b/lib/chef/dsl/include_attribute.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -55,7 +55,3 @@ class Chef
end
end
end
-
-# **DEPRECATED**
-# This used to be part of chef/mixin/language_include_attribute. Load the file to activate the deprecation code.
-require "chef/mixin/language_include_attribute"
diff --git a/lib/chef/dsl/include_recipe.rb b/lib/chef/dsl/include_recipe.rb
index 9abd7d135b..d217c91d4b 100644
--- a/lib/chef/dsl/include_recipe.rb
+++ b/lib/chef/dsl/include_recipe.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,7 +38,3 @@ class Chef
end
end
end
-
-# **DEPRECATED**
-# This used to be part of chef/mixin/language_include_recipe. Load the file to activate the deprecation code.
-require "chef/mixin/language_include_recipe"
diff --git a/lib/chef/dsl/platform_introspection.rb b/lib/chef/dsl/platform_introspection.rb
index dc309f9acb..2e31e0b95b 100644
--- a/lib/chef/dsl/platform_introspection.rb
+++ b/lib/chef/dsl/platform_introspection.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -262,7 +262,3 @@ class Chef
end
end
end
-
-# **DEPRECATED**
-# This used to be part of chef/mixin/language. Load the file to activate the deprecation code.
-require "chef/mixin/language"
diff --git a/lib/chef/dsl/recipe.rb b/lib/chef/dsl/recipe.rb
index dedf291857..9da812cec0 100644
--- a/lib/chef/dsl/recipe.rb
+++ b/lib/chef/dsl/recipe.rb
@@ -1,7 +1,7 @@
-#--
+#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -74,19 +74,9 @@ class Chef
def exec(args)
raise Chef::Exceptions::ResourceNotFound, "exec was called, but you probably meant to use an execute resource. If not, please call Kernel#exec explicitly. The exec block called was \"#{args}\""
end
-
- # @deprecated Use Chef::DSL::Recipe instead, will be removed in Chef 13
- module FullDSL
- include Chef::DSL::Recipe
- extend Chef::Mixin::LazyModuleInclude
- end
end
end
end
# Avoid circular references for things that are only used in instance methods
require "chef/resource"
-
-# **DEPRECATED**
-# This used to be part of chef/mixin/recipe_definition_dsl_core. Load the file to activate the deprecation code.
-require "chef/mixin/recipe_definition_dsl_core"
diff --git a/lib/chef/environment.rb b/lib/chef/environment.rb
index 621a122440..be05b58989 100644
--- a/lib/chef/environment.rb
+++ b/lib/chef/environment.rb
@@ -3,7 +3,7 @@
# Author:: Seth Falcon (<seth@chef.io>)
# Author:: John Keiser (<jkeiser@ospcode.com>)
# Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>)
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# Copyright:: Copyright 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -34,8 +34,6 @@ class Chef
include Chef::Mixin::ParamsValidate
include Chef::Mixin::FromFile
- attr_accessor :chef_server_rest
-
COMBINED_COOKBOOK_CONSTRAINT = /(.+)(?:[\s]+)((?:#{Chef::VersionConstraint::OPS.join('|')})(?:[\s]+).+)$/
def initialize(chef_server_rest: nil)
@@ -297,7 +295,7 @@ class Chef
def self.validate_cookbook_versions(cv)
return false unless cv.kind_of?(Hash)
- cv.each do |cookbook, version|
+ cv.each_value do |version|
return false unless Chef::Environment.validate_cookbook_version(version)
end
true
diff --git a/lib/chef/event_dispatch/base.rb b/lib/chef/event_dispatch/base.rb
index 0f8013f114..0886d63152 100644
--- a/lib/chef/event_dispatch/base.rb
+++ b/lib/chef/event_dispatch/base.rb
@@ -36,11 +36,11 @@ class Chef
end
# Called at the end a successful Chef run.
- def run_completed(node)
+ def run_completed(node, run_status)
end
# Called at the end of a failed Chef run.
- def run_failed(exception)
+ def run_failed(exception, run_status)
end
# Called right after ohai runs.
diff --git a/lib/chef/guard_interpreter/resource_guard_interpreter.rb b/lib/chef/guard_interpreter/resource_guard_interpreter.rb
index 6df60aec89..e245eab2c7 100644
--- a/lib/chef/guard_interpreter/resource_guard_interpreter.rb
+++ b/lib/chef/guard_interpreter/resource_guard_interpreter.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Edwards (<adamed@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -108,7 +108,7 @@ class Chef
def block_from_attributes(attributes)
Proc.new do
- attributes.keys.each do |attribute_name|
+ attributes.each_key do |attribute_name|
send(attribute_name, attributes[attribute_name]) if respond_to?(attribute_name)
end
end
diff --git a/lib/chef/handler.rb b/lib/chef/handler.rb
index 100ed23d9e..34db223d43 100644
--- a/lib/chef/handler.rb
+++ b/lib/chef/handler.rb
@@ -19,14 +19,12 @@ require "chef/client"
require "forwardable"
class Chef
- # == Chef::Handler
# The base class for an Exception or Notification Handler. Create your own
# handler by subclassing Chef::Handler. When a Chef run fails with an
# uncaught Exception, Chef will set the +run_status+ on your handler and call
# +report+
#
- # ===Example:
- #
+ # @example
# require 'net/smtp'
#
# module MyOrg
diff --git a/lib/chef/handler/json_file.rb b/lib/chef/handler/json_file.rb
index 9ba3d70383..7f29b91449 100644
--- a/lib/chef/handler/json_file.rb
+++ b/lib/chef/handler/json_file.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# Copyright:: Copyright 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,7 +28,6 @@ class Chef
def initialize(config = {})
@config = config
@config[:path] ||= "/var/chef/reports"
- @config
end
def report
diff --git a/lib/chef/http.rb b/lib/chef/http.rb
index 14dd8b93a5..241806da4e 100644
--- a/lib/chef/http.rb
+++ b/lib/chef/http.rb
@@ -5,7 +5,7 @@
# Author:: Christopher Brown (<cb@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2009-2017, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -170,11 +170,10 @@ class Chef
raise
end
- def streaming_request_with_progress(path, headers = {}, &progress_block)
+ def streaming_request_with_progress(path, headers = {}, tempfile = nil, &progress_block)
http_attempts ||= 0
url = create_url(path)
response, rest_request, return_value = nil, nil, nil
- tempfile = nil
data = nil
method = :GET
@@ -182,7 +181,7 @@ class Chef
response, rest_request, return_value = send_http_request(method, url, processed_headers, data) do |http_response|
if http_response.kind_of?(Net::HTTPSuccess)
- tempfile = stream_to_tempfile(url, http_response, &progress_block)
+ tempfile = stream_to_tempfile(url, http_response, tempfile, &progress_block)
end
apply_stream_complete_middleware(http_response, rest_request, return_value)
end
@@ -217,11 +216,10 @@ class Chef
#
# @yield [tempfile] block to process the tempfile
# @yieldparams [tempfile<Tempfile>] tempfile
- def streaming_request(path, headers = {})
+ def streaming_request(path, headers = {}, tempfile = nil)
http_attempts ||= 0
url = create_url(path)
response, rest_request, return_value = nil, nil, nil
- tempfile = nil
data = nil
method = :GET
@@ -229,7 +227,7 @@ class Chef
response, rest_request, return_value = send_http_request(method, url, processed_headers, data) do |http_response|
if http_response.kind_of?(Net::HTTPSuccess)
- tempfile = stream_to_tempfile(url, http_response)
+ tempfile = stream_to_tempfile(url, http_response, tempfile)
end
apply_stream_complete_middleware(http_response, rest_request, return_value)
end
@@ -500,11 +498,13 @@ class Chef
end
# @api private
- def stream_to_tempfile(url, response, &progress_block)
+ def stream_to_tempfile(url, response, tf = nil, &progress_block)
content_length = response["Content-Length"]
- tf = Tempfile.open("chef-rest")
- if Chef::Platform.windows?
- tf.binmode # required for binary files on Windows platforms
+ if tf.nil?
+ tf = Tempfile.open("chef-rest")
+ if Chef::Platform.windows?
+ tf.binmode # required for binary files on Windows platforms
+ end
end
Chef::Log.debug("Streaming download from #{url} to tempfile #{tf.path}")
# Stolen from http://www.ruby-forum.com/topic/166423
diff --git a/lib/chef/http/basic_client.rb b/lib/chef/http/basic_client.rb
index 9a000136e6..1539770aa8 100644
--- a/lib/chef/http/basic_client.rb
+++ b/lib/chef/http/basic_client.rb
@@ -5,7 +5,7 @@
# Author:: Christopher Brown (<cb@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -32,7 +32,6 @@ class Chef
HTTPS = "https".freeze
attr_reader :url
- attr_reader :http_client
attr_reader :ssl_policy
attr_reader :keepalives
diff --git a/lib/chef/http/http_request.rb b/lib/chef/http/http_request.rb
index 7fc1acb889..bd999d8f86 100644
--- a/lib/chef/http/http_request.rb
+++ b/lib/chef/http/http_request.rb
@@ -5,7 +5,7 @@
# Author:: Christopher Brown (<cb@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2009-2016, 2010-2016 Chef Software, Inc.
+# Copyright:: Copyright 2009-2016, 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -71,7 +71,7 @@ class Chef
@user_agent ||= DEFAULT_UA
end
- attr_reader :method, :url, :headers, :http_client, :http_request
+ attr_reader :method, :url, :headers, :http_request
def initialize(method, url, req_body, base_headers = {})
@method, @url = method, url
diff --git a/lib/chef/http/socketless_chef_zero_client.rb b/lib/chef/http/socketless_chef_zero_client.rb
index 296330815a..34a5dbb083 100644
--- a/lib/chef/http/socketless_chef_zero_client.rb
+++ b/lib/chef/http/socketless_chef_zero_client.rb
@@ -1,6 +1,6 @@
#--
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2015-2016, Chef Software, Inc.
+# Copyright:: Copyright 2015-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -133,7 +133,7 @@ class Chef
511 => "Network Authentication Required",
}
- STATUS_MESSAGE.values.each { |v| v.freeze }
+ STATUS_MESSAGE.each_value { |v| v.freeze }
STATUS_MESSAGE.freeze
def initialize(base_url)
diff --git a/lib/chef/knife.rb b/lib/chef/knife.rb
index aa30f2e2ed..2853bf65dd 100644
--- a/lib/chef/knife.rb
+++ b/lib/chef/knife.rb
@@ -42,9 +42,9 @@ class Chef
extend Chef::Mixin::ConvertToClassName
extend Forwardable
- # Backwards Compat:
- # Ideally, we should not vomit all of these methods into this base class;
- # instead, they should be accessed by hitting the ui object directly.
+ # @note Backwards Compat:
+ # Ideally, we should not vomit all of these methods into this base class;
+ # instead, they should be accessed by hitting the ui object directly.
def_delegator :@ui, :stdout
def_delegator :@ui, :stderr
def_delegator :@ui, :stdin
@@ -105,12 +105,11 @@ class Chef
# Explicitly set the category for the current command to +new_category+
# The category is normally determined from the first word of the command
# name, but some commands make more sense using two or more words
- # ===Arguments
- # new_category::: A String to set the category to (see examples)
- # ===Examples:
- # Data bag commands would be in the 'data' category by default. To put them
- # in the 'data bag' category:
- # category('data bag')
+ # @param new_category [String] value to set the category to (see examples)
+ #
+ # @example Data bag commands would be in the 'data' category by default. To
+ # put them in the 'data bag' category:
+ # category('data bag')
def self.category(new_category)
@category = new_category
end
@@ -178,11 +177,12 @@ class Chef
@config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log)
end
- def self.load_config(explicit_config_file)
+ def self.load_config(explicit_config_file, profile)
config_loader.explicit_config_file = explicit_config_file
+ config_loader.profile = profile
config_loader.load
- ui.warn("No knife configuration file found") if config_loader.no_config_found?
+ ui.warn("No knife configuration file found. See https://docs.chef.io/config_rb_knife.html for details.") if config_loader.no_config_found?
config_loader
rescue Exceptions::ConfigurationError => e
@@ -196,10 +196,11 @@ class Chef
# Run knife for the given +args+ (ARGV), adding +options+ to the list of
# CLI options that the subcommand knows how to handle.
- # ===Arguments
- # args::: usually ARGV
- # options::: A Mixlib::CLI option parser hash. These +options+ are how
- # subcommands know about global knife CLI options
+ #
+ # @param args [Array] The arguments. Usually ARGV
+ # @param options [Mixlib::CLI option parser hash] These +options+ are how
+ # subcommands know about global knife CLI options
+ #
def self.run(args, options = {})
# Fallback debug logging. Normally the logger isn't configured until we
# read the config, but this means any logging that happens before the
@@ -404,7 +405,7 @@ class Chef
def configure_chef
# knife needs to send logger output to STDERR by default
Chef::Config[:log_location] = STDERR
- config_loader = self.class.load_config(config[:config_file])
+ config_loader = self.class.load_config(config[:config_file], config[:profile])
config[:config_file] = config_loader.config_location
# For CLI options like `--config-option key=value`. These have to get
diff --git a/lib/chef/knife/bootstrap.rb b/lib/chef/knife/bootstrap.rb
index f9dca7896a..9decacce13 100644
--- a/lib/chef/knife/bootstrap.rb
+++ b/lib/chef/knife/bootstrap.rb
@@ -448,7 +448,7 @@ class Chef
ssh.config[:ssh_identity_file] = config[:ssh_identity_file] || config[:identity_file]
ssh.config[:manual] = true
ssh.config[:host_key_verify] = config[:host_key_verify]
- ssh.config[:on_error] = :raise
+ ssh.config[:on_error] = true
ssh
end
diff --git a/lib/chef/knife/client_delete.rb b/lib/chef/knife/client_delete.rb
index 38da5c2a73..82b521c7d1 100644
--- a/lib/chef/knife/client_delete.rb
+++ b/lib/chef/knife/client_delete.rb
@@ -32,7 +32,7 @@ class Chef
:long => "--delete-validators",
:description => "Force deletion of client if it's a validator"
- banner "knife client delete [CLIENT[,CLIENT]] (options)"
+ banner "knife client delete [CLIENT [CLIENT]] (options)"
def run
if @name_args.length == 0
diff --git a/lib/chef/knife/configure.rb b/lib/chef/knife/configure.rb
index 967a18de87..10ae62b6c9 100644
--- a/lib/chef/knife/configure.rb
+++ b/lib/chef/knife/configure.rb
@@ -17,6 +17,7 @@
#
require "chef/knife"
+require "chef/util/path_helper"
class Chef
class Knife
@@ -67,24 +68,22 @@ class Chef
end
def run
- ask_user_for_config_path
-
FileUtils.mkdir_p(chef_config_path)
+ config_file = File.join(chef_config_path, "credentials")
ask_user_for_config
- ::File.open(config[:config_file], "w") do |f|
+ config_file = File.expand_path(config_file)
+ if File.exist?(config_file)
+ confirm("Overwrite #{config_file}?")
+ end
+ ::File.open(config_file, "w") do |f|
f.puts <<-EOH
-node_name '#{new_client_name}'
-client_key '#{new_client_key}'
-validation_client_name '#{validation_client_name}'
-validation_key '#{validation_key}'
-chef_server_url '#{chef_server}'
-syntax_check_cache_path '#{File.join(chef_config_path, "syntax_check_cache")}'
+[default]
+client_name = '#{new_client_name}'
+client_key = '#{new_client_key}'
+chef_server_url = '#{chef_server}'
EOH
- unless chef_repo.empty?
- f.puts "cookbook_path [ '#{chef_repo}/cookbooks' ]"
- end
end
if config[:initial]
@@ -109,26 +108,11 @@ EOH
ui.msg("Before running commands with Knife")
ui.msg("")
ui.msg("*****")
- ui.msg("")
- ui.msg("You must place your validation key in:")
- ui.msg(" #{validation_key}")
- ui.msg("Before generating instance data with Knife")
- ui.msg("")
- ui.msg("*****")
end
ui.msg("Configuration file written to #{config[:config_file]}")
end
- def ask_user_for_config_path
- config[:config_file] ||= ask_question("Where should I put the config file? ", :default => "#{Chef::Config[:user_home]}/.chef/knife.rb")
- # have to use expand path to expand the tilde character to the user's home
- config[:config_file] = File.expand_path(config[:config_file])
- if File.exists?(config[:config_file])
- confirm("Overwrite #{config[:config_file]}")
- end
- end
-
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}/organizations/myorg")
@@ -140,10 +124,6 @@ EOH
else
@new_client_name = config[:node_name] || ask_question("Please enter an existing username or clientname for the API: ", :default => Etc.getlogin)
end
- @validation_client_name = config[:validation_client_name] || ask_question("Please enter the validation clientname: ", :default => "chef-validator")
- @validation_key = config[:validation_key] || ask_question("Please enter the location of the validation key: ", :default => "/etc/chef-server/chef-validator.pem")
- @validation_key = File.expand_path(@validation_key)
- @chef_repo = config[:repository] || ask_question("Please enter the path to a chef repository (or leave blank): ")
@new_client_key = config[:client_key] || File.join(chef_config_path, "#{@new_client_name}.pem")
@new_client_key = File.expand_path(@new_client_key)
@@ -157,12 +137,8 @@ EOH
o[:fqdn] || o[:machinename] || o[:hostname] || "localhost"
end
- def config_file
- config[:config_file]
- end
-
def chef_config_path
- File.dirname(config_file)
+ Chef::Util::PathHelper.home(".chef")
end
end
end
diff --git a/lib/chef/knife/cookbook_metadata.rb b/lib/chef/knife/cookbook_metadata.rb
index 29eba6a36a..e089c4b777 100644
--- a/lib/chef/knife/cookbook_metadata.rb
+++ b/lib/chef/knife/cookbook_metadata.rb
@@ -1,7 +1,7 @@
#
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,7 +47,7 @@ class Chef
if config[:all]
cl = Chef::CookbookLoader.new(config[:cookbook_path])
cl.load_cookbooks
- cl.each do |cname, cookbook|
+ cl.each_key do |cname|
generate_metadata(cname.to_s)
end
else
diff --git a/lib/chef/knife/cookbook_site_install.rb b/lib/chef/knife/cookbook_site_install.rb
index 72fb426554..f4d692e13c 100644
--- a/lib/chef/knife/cookbook_site_install.rb
+++ b/lib/chef/knife/cookbook_site_install.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# Copyright:: Copyright 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -116,7 +116,7 @@ class Chef
end
unless config[:no_deps]
- preferred_metadata.dependencies.each do |cookbook, version_list|
+ preferred_metadata.dependencies.each_key do |cookbook|
# Doesn't do versions.. yet
nv = self.class.new
nv.config = config
diff --git a/lib/chef/knife/cookbook_test.rb b/lib/chef/knife/cookbook_test.rb
index 5c6dd32f37..f3a4981c95 100644
--- a/lib/chef/knife/cookbook_test.rb
+++ b/lib/chef/knife/cookbook_test.rb
@@ -2,7 +2,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Matthew Kent (<mkent@magoazul.com>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# Copyright:: Copyright 2010-2016, Matthew Kent
# License:: Apache License, Version 2.0
#
@@ -50,7 +50,7 @@ class Chef
if config[:all]
cl = cookbook_loader
cl.load_cookbooks
- cl.each do |key, cookbook|
+ cl.each_key do |key|
checked_a_cookbook = true
test_cookbook(key)
end
diff --git a/lib/chef/knife/cookbook_upload.rb b/lib/chef/knife/cookbook_upload.rb
index 6938ac280d..f67a26dc9a 100644
--- a/lib/chef/knife/cookbook_upload.rb
+++ b/lib/chef/knife/cookbook_upload.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Nuo Yan (<yan.nuo@gmail.com>)
-# Copyright:: Copyright 2009-2016, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -146,12 +146,12 @@ class Chef
end
if upload_failures == 0
- ui.info "Uploaded #{upload_ok} cookbook#{upload_ok > 1 ? "s" : ""}."
+ ui.info "Uploaded #{upload_ok} cookbook#{upload_ok == 1 ? "" : "s"}."
elsif upload_failures > 0 && upload_ok > 0
- ui.warn "Uploaded #{upload_ok} cookbook#{upload_ok > 1 ? "s" : ""} ok but #{upload_failures} " +
- "cookbook#{upload_failures > 1 ? "s" : ""} upload failed."
+ ui.warn "Uploaded #{upload_ok} cookbook#{upload_ok == 1 ? "" : "s"} ok but #{upload_failures} " +
+ "cookbook#{upload_failures == 1 ? "" : "s"} upload failed."
elsif upload_failures > 0 && upload_ok == 0
- ui.error "Failed to upload #{upload_failures} cookbook#{upload_failures > 1 ? "s" : ""}."
+ ui.error "Failed to upload #{upload_failures} cookbook#{upload_failures == 1 ? "" : "s"}."
exit 1
end
end
@@ -172,7 +172,7 @@ class Chef
if ! upload_set.has_key?(cookbook_name)
upload_set[cookbook_name] = cookbook_repo[cookbook_name]
if config[:depends]
- upload_set[cookbook_name].metadata.dependencies.each { |dep, ver| @name_args << dep }
+ upload_set[cookbook_name].metadata.dependencies.each_key { |dep| @name_args << dep }
end
end
rescue Exceptions::CookbookNotFoundInRepo => e
diff --git a/lib/chef/knife/core/bootstrap_context.rb b/lib/chef/knife/core/bootstrap_context.rb
index 9b16b94910..adbdee1858 100644
--- a/lib/chef/knife/core/bootstrap_context.rb
+++ b/lib/chef/knife/core/bootstrap_context.rb
@@ -255,7 +255,7 @@ validation_client_name "#{@chef_config[:validation_client_name]}"
content << "mkdir #{file_on_node}\n"
else
content << "cat > #{file_on_node} <<'EOP'\n" +
- f.read + "\nEOP\n"
+ f.read.gsub("'", "'\\\\''") + "\nEOP\n"
end
end
end
diff --git a/lib/chef/knife/core/status_presenter.rb b/lib/chef/knife/core/status_presenter.rb
index f55f9abcbb..1e2d9b41b6 100644
--- a/lib/chef/knife/core/status_presenter.rb
+++ b/lib/chef/knife/core/status_presenter.rb
@@ -101,23 +101,32 @@ class Chef
fqdn = (node[:ec2] && node[:ec2][:public_hostname]) || node[:fqdn]
name = node["name"] || node.name
- hours, minutes, = time_difference_in_hms(node["ohai_time"])
- hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}"
- minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}"
run_list = "#{node['run_list']}" if config[:run_list]
- if hours > 24
- color = :red
- text = hours_text
- elsif hours >= 1
- color = :yellow
- text = hours_text
+ line_parts = Array.new
+
+ if node["ohai_time"]
+ hours, minutes, seconds = time_difference_in_hms(node["ohai_time"])
+ hours_text = "#{hours} hour#{hours == 1 ? ' ' : 's'}"
+ minutes_text = "#{minutes} minute#{minutes == 1 ? ' ' : 's'}"
+ seconds_text = "#{seconds} second#{seconds == 1 ? ' ' : 's'}"
+ if hours > 24
+ color = :red
+ text = hours_text
+ elsif hours >= 1
+ color = :yellow
+ text = hours_text
+ elsif minutes >= 1
+ color = :green
+ text = minutes_text
+ else
+ color = :green
+ text = seconds_text
+ end
+ line_parts << @ui.color(text, color) + " ago" << name
else
- color = :green
- text = minutes_text
+ line_parts << "Node #{name} has not yet converged"
end
- line_parts = Array.new
- line_parts << @ui.color(text, color) + " ago" << name
line_parts << fqdn if fqdn
line_parts << ip if ip
line_parts << run_list if run_list
diff --git a/lib/chef/knife/core/ui.rb b/lib/chef/knife/core/ui.rb
index 484c3ab3de..b2efbd8b8f 100644
--- a/lib/chef/knife/core/ui.rb
+++ b/lib/chef/knife/core/ui.rb
@@ -172,7 +172,7 @@ class Chef
tf.sync = true
tf.puts output
tf.close
- raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_using.html for details." unless system("#{config[:editor]} #{tf.path}")
+ raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup.html for details." unless system("#{config[:editor]} #{tf.path}")
output = IO.read(tf.path)
end
diff --git a/lib/chef/knife/data_bag_secret_options.rb b/lib/chef/knife/data_bag_secret_options.rb
index 4246c9edfa..a612004e15 100644
--- a/lib/chef/knife/data_bag_secret_options.rb
+++ b/lib/chef/knife/data_bag_secret_options.rb
@@ -95,7 +95,7 @@ class Chef
##
# Determine if the user has specified an appropriate secret for encrypting data bag items.
- # @returns boolean
+ # @return boolean
def base_encryption_secret_provided?(need_encrypt_flag = true)
validate_secrets
diff --git a/lib/chef/knife/data_bag_show.rb b/lib/chef/knife/data_bag_show.rb
index ea9c390f19..5df0561276 100644
--- a/lib/chef/knife/data_bag_show.rb
+++ b/lib/chef/knife/data_bag_show.rb
@@ -51,7 +51,7 @@ class Chef
ui.warn("Encrypted data bag detected, but no secret provided for decoding. Displaying encrypted data.")
format_for_display(raw_data)
else
- ui.warn("Unencrypted data bag detected, ignoring any provided secret options.")
+ ui.warn("Unencrypted data bag detected, ignoring any provided secret options.") if secret
format_for_display(raw_data)
end
diff --git a/lib/chef/knife/edit.rb b/lib/chef/knife/edit.rb
index 46903e7420..4d7338f9f6 100644
--- a/lib/chef/knife/edit.rb
+++ b/lib/chef/knife/edit.rb
@@ -58,7 +58,7 @@ class Chef
# Let the user edit the temporary file
if !system("#{config[:editor]} #{file.path}")
- raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_using.html for details."
+ raise "Please set EDITOR environment variable. See https://docs.chef.io/knife_setup.html for details."
end
result_text = IO.read(file.path)
diff --git a/lib/chef/knife/environment_compare.rb b/lib/chef/knife/environment_compare.rb
index 8a2ef853d3..2e70783d3f 100644
--- a/lib/chef/knife/environment_compare.rb
+++ b/lib/chef/knife/environment_compare.rb
@@ -94,17 +94,17 @@ class Chef
def cookbook_list(constraints)
result = {}
- constraints.each { |env, cb| result.merge!(cb) }
+ constraints.each_value { |cb| result.merge!(cb) }
result
end
def matrix_output(cookbooks, constraints)
rows = [ "" ]
environments = []
- constraints.each { |e, v| environments << e.to_s }
+ constraints.each_key { |e| environments << e.to_s }
columns = environments.count + 1
environments.each { |env| rows << ui.color(env, :bold) }
- cookbooks.each do |c, v|
+ cookbooks.each_key do |c|
total = []
environments.each { |n| total << constraints[n][c] }
if total.uniq.count == 1
diff --git a/lib/chef/knife/index_rebuild.rb b/lib/chef/knife/index_rebuild.rb
deleted file mode 100644
index 206b7b0fbf..0000000000
--- a/lib/chef/knife/index_rebuild.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/knife"
-
-class Chef
- class Knife
- class IndexRebuild < Knife
-
- banner "knife index rebuild (options)"
- option :yes,
- :short => "-y",
- :long => "--yes",
- :boolean => true,
- :description => "don't bother to ask if I'm sure"
-
- def run
- api_info = grab_api_info
-
- if unsupported_version?(api_info)
- unsupported_server_message(api_info)
- exit 1
- else
- deprecated_server_message
- nag
- output rest.post("/search/reindex", {})
- end
- end
-
- def grab_api_info
- # Since we don't yet have any endpoints that implement an
- # OPTIONS handler, we need to get our version header
- # information in a more roundabout way. We'll try to query
- # for a node we know won't exist; the 404 response that comes
- # back will give us what we want
- dummy_node = "knife_index_rebuild_test_#{rand(1000000)}"
- rest.get("/nodes/#{dummy_node}")
- rescue Net::HTTPServerException => exception
- r = exception.response
- parse_api_info(r)
- end
-
- # Only Chef 11+ servers will have version information in their
- # headers, and only those servers will lack an API endpoint for
- # index rebuilding.
- def unsupported_version?(api_info)
- !!api_info["version"]
- end
-
- def unsupported_server_message(api_info)
- ui.error("Rebuilding the index is not available via knife for #{server_type(api_info)}s version 11.0.0 and above.")
- ui.info("Instead, run the '#{ctl_command(api_info)} reindex' command on the server itself.")
- end
-
- def deprecated_server_message
- ui.warn("'knife index rebuild' has been removed for Chef 11+ servers. It will continue to work for prior versions, however.")
- end
-
- def nag
- ui.info("This operation is destructive. Rebuilding the index may take some time.")
- ui.confirm("Continue")
- end
-
- # Chef 11 (and above) servers return various pieces of
- # information about the server in an +x-ops-api-info+ header.
- # This is a +;+ delimited string of key / value pairs, separated
- # by +=+.
- #
- # Given a Net::HTTPResponse object, this method extracts this
- # information (if present), and returns it as a hash. If no
- # such header is found, an empty hash is returned.
- def parse_api_info(response)
- value = response["x-ops-api-info"]
- if value
- kv = value.split(";")
- kv.inject({}) do |acc, pair|
- k, v = pair.split("=")
- acc[k] = v
- acc
- end
- else
- {}
- end
- end
-
- # Given an API info hash (see +#parse_api_info(response)+),
- # return a string describing the kind of server we're
- # interacting with (based on the +flavor+ field)
- def server_type(api_info)
- case api_info["flavor"]
- when "osc"
- "Open Source Chef Server"
- when "opc"
- "Private Chef Server"
- else
- # Generic fallback
- "Chef Server"
- end
- end
-
- # Given an API info hash (see +#parse_api_info(response)+),
- # return the name of the "server-ctl" command for the kind of
- # server we're interacting with (based on the +flavor+ field)
- def ctl_command(api_info)
- case api_info["flavor"]
- when "osc"
- "chef-server-ctl"
- when "opc"
- "private-chef-ctl"
- else
- # Generic fallback
- "chef-server-ctl"
- end
- end
-
- end
- end
-end
diff --git a/lib/chef/knife/node_delete.rb b/lib/chef/knife/node_delete.rb
index b03569cded..52b8d122ca 100644
--- a/lib/chef/knife/node_delete.rb
+++ b/lib/chef/knife/node_delete.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife node delete [NODE[,NODE]] (options)"
+ banner "knife node delete [NODE [NODE]] (options)"
def run
if @name_args.length == 0
diff --git a/lib/chef/knife/node_policy_set.rb b/lib/chef/knife/node_policy_set.rb
new file mode 100644
index 0000000000..404446fe0e
--- /dev/null
+++ b/lib/chef/knife/node_policy_set.rb
@@ -0,0 +1,79 @@
+#
+# Author:: Piyush Awasthi (<piyush.awasthi@chef.io>)
+# Copyright:: Copyright 2017-2018, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the License);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/knife"
+
+class Chef
+ class Knife
+ class NodePolicySet < Knife
+
+ deps do
+ require "chef/node"
+ require "chef/json_compat"
+ end
+
+ banner "knife node policy set NODE POLICY_GROUP POLICY_NAME (options)"
+
+ def run
+ validate_node!
+ validate_options!
+ node = Chef::Node.load(@name_args[0])
+ set_policy(node)
+ if node.save
+ ui.info "Successfully set the policy on node #{node.name}"
+ else
+ ui.info "Error in updating node #{node.name}"
+ end
+ end
+
+ private
+
+ # Set policy name and group to node
+ def set_policy(node)
+ policy_group, policy_name = @name_args[1..-1]
+ node.policy_name = policy_name
+ node.policy_group = policy_group
+ end
+
+ # Validate policy name and policy group
+ def validate_options!
+ if incomplete_policyfile_options?
+ ui.error("Policy group and name must be specified together")
+ exit 1
+ end
+ true
+ end
+
+ # Validate node pass in CLI
+ def validate_node!
+ if @name_args[0].nil?
+ ui.error("You must specify a node name")
+ show_usage
+ exit 1
+ end
+ end
+
+ # True if one of policy_name or policy_group was given, but not both
+ def incomplete_policyfile_options?
+ policy_group, policy_name = @name_args[1..-1]
+ (policy_group.nil? || policy_name.nil? || @name_args[1..-1].size > 2)
+ end
+
+ end
+ end
+end
diff --git a/lib/chef/knife/node_run_list_add.rb b/lib/chef/knife/node_run_list_add.rb
index f8d40c8321..fb4ce3bc12 100644
--- a/lib/chef/knife/node_run_list_add.rb
+++ b/lib/chef/knife/node_run_list_add.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife node run_list add [NODE] [ENTRY[,ENTRY]] (options)"
+ banner "knife node run_list add [NODE] [ENTRY [ENTRY]] (options)"
option :after,
:short => "-a ITEM",
diff --git a/lib/chef/knife/node_run_list_remove.rb b/lib/chef/knife/node_run_list_remove.rb
index 3f9cdabfff..df50818c23 100644
--- a/lib/chef/knife/node_run_list_remove.rb
+++ b/lib/chef/knife/node_run_list_remove.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife node run_list remove [NODE] [ENTRY[,ENTRY]] (options)"
+ banner "knife node run_list remove [NODE] [ENTRY [ENTRY]] (options)"
def run
node = Chef::Node.load(@name_args[0])
diff --git a/lib/chef/knife/role_env_run_list_add.rb b/lib/chef/knife/role_env_run_list_add.rb
index 61aec506a9..4a3bb70641 100644
--- a/lib/chef/knife/role_env_run_list_add.rb
+++ b/lib/chef/knife/role_env_run_list_add.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role env_run_list add [ROLE] [ENVIRONMENT] [ENTRY[,ENTRY]] (options)"
+ banner "knife role env_run_list add [ROLE] [ENVIRONMENT] [ENTRY [ENTRY]] (options)"
option :after,
:short => "-a ITEM",
diff --git a/lib/chef/knife/role_run_list_add.rb b/lib/chef/knife/role_run_list_add.rb
index 6aa92d37ba..7eaaa136bb 100644
--- a/lib/chef/knife/role_run_list_add.rb
+++ b/lib/chef/knife/role_run_list_add.rb
@@ -27,7 +27,7 @@ class Chef
require "chef/json_compat"
end
- banner "knife role run_list add [ROLE] [ENTRY[,ENTRY]] (options)"
+ banner "knife role run_list add [ROLE] [ENTRY [ENTRY]] (options)"
option :after,
:short => "-a ITEM",
diff --git a/lib/chef/knife/search.rb b/lib/chef/knife/search.rb
index c4c3380734..94c33aa594 100644
--- a/lib/chef/knife/search.rb
+++ b/lib/chef/knife/search.rb
@@ -91,12 +91,16 @@ class Chef
search_args[:filter_result] = create_result_filter(config[:filter_result])
elsif (not ui.config[:attribute].nil?) && (not ui.config[:attribute].empty?)
search_args[:filter_result] = create_result_filter_from_attributes(ui.config[:attribute])
+ elsif config[:id_only]
+ search_args[:filter_result] = create_result_filter_from_attributes([])
end
begin
q.search(@type, @query, search_args) do |item|
formatted_item = Hash.new
- if item.is_a?(Hash)
+ if config[:id_only]
+ formatted_item = format_for_display({ "id" => item["__display_name"] })
+ elsif item.is_a?(Hash)
# doing a little magic here to set the correct name
formatted_item[item["__display_name"]] = item.reject { |k| k == "__display_name" }
else
diff --git a/lib/chef/knife/ssh.rb b/lib/chef/knife/ssh.rb
index ae14ce9954..8e13425f82 100644
--- a/lib/chef/knife/ssh.rb
+++ b/lib/chef/knife/ssh.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2009-2017, Chef Software Inc.
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -46,11 +46,10 @@ class Chef
:default => nil,
:proc => lambda { |o| o.to_i }
- option :attribute,
+ option :ssh_attribute,
:short => "-a ATTR",
:long => "--attribute ATTR",
- :description => "The attribute to use for opening the connection - default depends on the context",
- :proc => Proc.new { |key| Chef::Config[:knife][:ssh_attribute] = key.strip }
+ :description => "The attribute to use for opening the connection - default depends on the context"
option :manual,
:short => "-m",
@@ -59,6 +58,10 @@ class Chef
:description => "QUERY is a space separated list of servers",
:default => false
+ option :prefix_attribute,
+ :long => "--prefix-attribute ATTR",
+ :description => "The attribute to use for prefixing the ouput - default depends on the context"
+
option :ssh_user,
:short => "-x USERNAME",
:long => "--ssh-user USERNAME",
@@ -102,10 +105,6 @@ class Chef
:description => "Enable SSH agent forwarding",
:boolean => true
- option :identity_file,
- :long => "--identity-file IDENTITY_FILE",
- :description => "The SSH identity file used for authentication. [DEPRECATED] Use --ssh-identity-file instead."
-
option :ssh_identity_file,
:short => "-i IDENTITY_FILE",
:long => "--ssh-identity-file IDENTITY_FILE",
@@ -122,7 +121,7 @@ class Chef
:long => "--exit-on-error",
:description => "Immediately exit if an error is encountered",
:boolean => true,
- :proc => Proc.new { :raise }
+ :default => false
option :tmux_split,
:long => "--tmux-split",
@@ -131,15 +130,13 @@ class Chef
:default => false
def session
- config[:on_error] ||= :skip
ssh_error_handler = Proc.new do |server|
- case config[:on_error]
- when :skip
- ui.warn "Failed to connect to #{server.host} -- #{$!.class.name}: #{$!.message}"
- $!.backtrace.each { |l| Chef::Log.debug(l) }
- when :raise
+ if config[:on_error]
#Net::SSH::Multi magic to force exception to be re-raised.
throw :go, :raise
+ else
+ ui.warn "Failed to connect to #{server.host} -- #{$!.class.name}: #{$!.message}"
+ $!.backtrace.each { |l| Chef::Log.debug(l) }
end
end
@@ -181,27 +178,34 @@ class Chef
session_from_list(list)
end
- def get_ssh_attribute(node)
+ def get_prefix_attribute(item)
+ # Order of precedence for prefix
+ # 1) config value (cli or knife config)
+ # 2) nil
+ msg = "Using node attribute '%s' as the prefix: %s"
+ if item["prefix"]
+ Chef::Log.debug(sprintf(msg, config[:prefix_attribute], item["prefix"]))
+ item["prefix"]
+ else
+ nil
+ end
+ end
+
+ def get_ssh_attribute(item)
# Order of precedence for ssh target
- # 1) command line attribute
- # 2) configuration file
- # 3) cloud attribute
- # 4) fqdn
- 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]}: #{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"]
+ # 1) config value (cli or knife config)
+ # 2) cloud attribute
+ # 3) fqdn
+ msg = "Using node attribute '%s' as the ssh target: %s"
+ if item["target"]
+ Chef::Log.debug(sprintf(msg, config[:ssh_attribute], item["target"]))
+ item["target"]
+ elsif !item.dig("cloud", "public_hostname").to_s.empty?
+ Chef::Log.debug(sprintf(msg, "cloud.public_hostname", item["cloud"]["public_hostname"]))
+ item["cloud"]["public_hostname"]
else
- # falling back to default of fqdn
- Chef::Log.debug("Using node attribute 'fqdn' as the ssh target: #{node["fqdn"]}")
- node["fqdn"]
+ Chef::Log.debug(sprintf(msg, "fqdn", item["fqdn"]))
+ item["fqdn"]
end
end
@@ -212,14 +216,12 @@ class Chef
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)
+ if config[:prefix_attribute]
+ required_attributes[:prefix] = config[:prefix_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)
+ if config[:ssh_attribute]
+ required_attributes[:target] = config[:ssh_attribute].split(separator)
end
@search_count = 0
@@ -232,8 +234,9 @@ class Chef
# returned node object
host = get_ssh_attribute(item)
next if host.nil?
- ssh_port = item[:cloud].nil? ? nil : item[:cloud][:public_ssh_port]
- srv = [host, ssh_port]
+ prefix = get_prefix_attribute(item)
+ ssh_port = item.dig("cloud", "public_ssh_port")
+ srv = [host, ssh_port, prefix]
list.push(srv)
end
@@ -282,7 +285,8 @@ class Chef
def session_from_list(list)
list.each do |item|
- host, ssh_port = item
+ host, ssh_port, prefix = item
+ prefix = host unless prefix
Chef::Log.debug("Adding #{host}")
session_opts = session_options(host, ssh_port)
# Handle port overrides for the main connection.
@@ -291,19 +295,21 @@ class Chef
# Handle connection timeout
session_opts[:timeout] = Chef::Config[:knife][:ssh_timeout] if Chef::Config[:knife][:ssh_timeout]
session_opts[:timeout] = config[:ssh_timeout] if config[:ssh_timeout]
+ # Handle session prefix
+ session_opts[:properties] = { prefix: prefix }
# Create the hostspec.
hostspec = session_opts[:user] ? "#{session_opts.delete(:user)}@#{host}" : host
# Connect a new session on the multi.
session.use(hostspec, session_opts)
- @longest = host.length if host.length > @longest
+ @longest = prefix.length if prefix.length > @longest
end
session
end
def fixup_sudo(command)
- command.sub(/^sudo/, 'sudo -p \'knife sudo password: \'')
+ command.sub(/^sudo/, "sudo -p 'knife sudo password: '")
end
def print_data(host, data)
@@ -342,9 +348,9 @@ class Chef
chan.exec command do |ch, success|
raise ArgumentError, "Cannot execute #{command}" unless success
ch.on_data do |ichannel, data|
- print_data(ichannel[:host], data)
+ print_data(ichannel.connection[:prefix], data)
if data =~ /^knife sudo password: /
- print_data(ichannel[:host], "\n")
+ print_data(ichannel.connection[:prefix], "\n")
ichannel.send_data("#{get_password}\n")
end
end
@@ -461,7 +467,7 @@ class Chef
end.join(" \\; ")
end
- tmux_name = "'knife ssh #{@name_args[0].tr(':', '=')}'"
+ tmux_name = "'knife ssh #{@name_args[0].tr(':.', '=-')}'"
begin
server = session.servers_for.first
cmd = ["tmux new-session -d -s #{tmux_name}",
@@ -557,8 +563,7 @@ class Chef
end
def configure_ssh_identity_file
- # config[:identity_file] is DEPRECATED in favor of :ssh_identity_file
- config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file] || config[:identity_file] || Chef::Config[:knife][:ssh_identity_file])
+ config[:ssh_identity_file] = get_stripped_unfrozen_value(config[:ssh_identity_file] || Chef::Config[:knife][:ssh_identity_file])
end
def configure_ssh_gateway_identity
@@ -588,10 +593,6 @@ class Chef
macterm
when "cssh"
cssh
- when "csshx"
- Chef::Log.warn("knife ssh csshx will be deprecated in a future release")
- Chef::Log.warn("please use knife ssh cssh instead")
- cssh
else
ssh_command(@name_args[1..-1].join(" "))
end
diff --git a/lib/chef/knife/user_create.rb b/lib/chef/knife/user_create.rb
index d21afb1059..c4a89f3707 100644
--- a/lib/chef/knife/user_create.rb
+++ b/lib/chef/knife/user_create.rb
@@ -78,6 +78,8 @@ knife user create for Open Source 11 Server is being deprecated.
Open Source 11 Server user commands now live under the knife osc_user namespace.
For backwards compatibility, we will forward this request to knife osc_user create.
If you are using an Open Source 11 Server, please use that command to avoid this warning.
+NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
+in Chef 15 which will be released April 2019.
EOF
end
diff --git a/lib/chef/knife/user_delete.rb b/lib/chef/knife/user_delete.rb
index cc92b4b36c..abfb45253e 100644
--- a/lib/chef/knife/user_delete.rb
+++ b/lib/chef/knife/user_delete.rb
@@ -37,6 +37,8 @@ knife user delete for Open Source 11 Server is being deprecated.
Open Source 11 Server user commands now live under the knife osc_user namespace.
For backwards compatibility, we will forward this request to knife osc_user delete.
If you are using an Open Source 11 Server, please use that command to avoid this warning.
+NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
+in Chef 15 which will be released April 2019.
EOF
end
diff --git a/lib/chef/knife/user_edit.rb b/lib/chef/knife/user_edit.rb
index bb80ede267..d184b85a6c 100644
--- a/lib/chef/knife/user_edit.rb
+++ b/lib/chef/knife/user_edit.rb
@@ -37,6 +37,8 @@ knife user edit for Open Source 11 Server is being deprecated.
Open Source 11 Server user commands now live under the knife oc_user namespace.
For backwards compatibility, we will forward this request to knife osc_user edit.
If you are using an Open Source 11 Server, please use that command to avoid this warning.
+NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
+in Chef 15 which will be released April 2019.
EOF
end
diff --git a/lib/chef/knife/user_reregister.rb b/lib/chef/knife/user_reregister.rb
index 8d2f2c1e73..172629faea 100644
--- a/lib/chef/knife/user_reregister.rb
+++ b/lib/chef/knife/user_reregister.rb
@@ -37,6 +37,8 @@ knife user reregister for Open Source 11 Server is being deprecated.
Open Source 11 Server user commands now live under the knife osc_user namespace.
For backwards compatibility, we will forward this request to knife osc_user reregister.
If you are using an Open Source 11 Server, please use that command to avoid this warning.
+NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
+in Chef 15 which will be released April 2019.
EOF
end
diff --git a/lib/chef/knife/user_show.rb b/lib/chef/knife/user_show.rb
index 04251c0863..6ba4ab5016 100644
--- a/lib/chef/knife/user_show.rb
+++ b/lib/chef/knife/user_show.rb
@@ -39,6 +39,8 @@ knife user show for Open Source 11 Server is being deprecated.
Open Source 11 Server user commands now live under the knife osc_user namespace.
For backwards compatibility, we will forward this request to knife osc_user show.
If you are using an Open Source 11 Server, please use that command to avoid this warning.
+NOTE: Backwards compatibility for Open Source 11 Server in these commands will be removed
+in Chef 15 which will be released April 2019.
EOF
end
diff --git a/lib/chef/knife/xargs.rb b/lib/chef/knife/xargs.rb
index 7f436d7936..a316fb8cf7 100644
--- a/lib/chef/knife/xargs.rb
+++ b/lib/chef/knife/xargs.rb
@@ -181,7 +181,7 @@ class Chef
def destroy_tempfiles(tempfiles)
# Unlink the files now that we're done with them
- tempfiles.keys.each { |tempfile| tempfile.close! }
+ tempfiles.each_key { |tempfile| tempfile.close! }
end
def xargs_files(command, tempfiles)
diff --git a/lib/chef/mixin/api_version_request_handling.rb b/lib/chef/mixin/api_version_request_handling.rb
index b91a1dfe0a..5566addf1d 100644
--- a/lib/chef/mixin/api_version_request_handling.rb
+++ b/lib/chef/mixin/api_version_request_handling.rb
@@ -19,11 +19,9 @@
class Chef
module Mixin
module ApiVersionRequestHandling
- # Input:
- # exeception:
- # Net::HTTPServerException that may or may not contain the x-ops-server-api-version header
+ # @param exeception [Net::HTTPServerException] may or may not contain the x-ops-server-api-version header
# supported_client_versions:
- # An array of Integers that represent the API versions the client supports.
+ # @param supported_client_versions [Array<Integer>] The API versions the client supports.
#
# Output:
# nil:
diff --git a/lib/chef/mixin/deprecation.rb b/lib/chef/mixin/deprecation.rb
index 14414036e7..6621555585 100644
--- a/lib/chef/mixin/deprecation.rb
+++ b/lib/chef/mixin/deprecation.rb
@@ -23,24 +23,24 @@ class Chef
@deprecated_constants ||= {}
end
- # Add a deprecated constant to the Chef::Mixin namespace.
- # === Arguments
- # * name: the constant name, as a relative symbol.
- # * replacement: the constant to return instead.
- # * message: A message telling the user what to do instead.
- # === Example:
- # deprecate_constant(:RecipeDefinitionDSLCore, Chef::DSL::Recipe, <<-EOM)
- # Chef::Mixin::RecipeDefinitionDSLCore is deprecated, use Chef::DSL::Recipe instead.
- # EOM
+ # Add a deprecated constant to the Chef::Mixin namespace.
+ #
+ # @param name [Symbol] the constant name, as a relative symbol.
+ # @param replacement [Object] the constant to return instead.
+ # @param message [String] A message telling the user what to do instead.
+ # @example
+ # deprecate_constant(:RecipeDefinitionDSLCore, Chef::DSL::Recipe, <<-EOM)
+ # Chef::Mixin::RecipeDefinitionDSLCore is deprecated, use Chef::DSL::Recipe instead.
+ # EOM
def self.deprecate_constant(name, replacement, message)
deprecated_constants[name] = { :replacement => replacement, :message => message }
end
- # Const missing hook to look up deprecated constants defined with
- # deprecate_constant. Emits a warning to the logger and returns the
- # replacement constant. Will call super, most likely causing an exception
- # for the missing constant, if +name+ is not found in the
- # deprecated_constants collection.
+ # Const missing hook to look up deprecated constants defined with
+ # deprecate_constant. Emits a warning to the logger and returns the
+ # replacement constant. Will call super, most likely causing an exception
+ # for the missing constant, if +name+ is not found in the
+ # deprecated_constants collection.
def self.const_missing(name)
if new_const = deprecated_constants[name]
Chef::Log.warn(new_const[:message])
diff --git a/lib/chef/mixin/homebrew_user.rb b/lib/chef/mixin/homebrew_user.rb
index 888c1bcbfd..6e32043c77 100644
--- a/lib/chef/mixin/homebrew_user.rb
+++ b/lib/chef/mixin/homebrew_user.rb
@@ -34,6 +34,7 @@ class Chef
# This tries to find the user to execute brew as. If a user is provided, that overrides the brew
# executable user. It is an error condition if the brew executable owner is root or we cannot find
# the brew executable.
+ # @param provided_user [String]
def find_homebrew_uid(provided_user = nil)
# They could provide us a user name or a UID
if provided_user
diff --git a/lib/chef/mixin/language.rb b/lib/chef/mixin/language.rb
deleted file mode 100644
index 3f53645a55..0000000000
--- a/lib/chef/mixin/language.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/dsl/platform_introspection"
-require "chef/dsl/data_query"
-require "chef/mixin/deprecation"
-
-class Chef
- module Mixin
-
- # == [DEPRECATED] Chef::Mixin::DeprecatedLanguageModule
- # This module is a temporary replacement for the previous
- # Chef::Mixin::Language. That module's functionality was split into two
- # modules, Chef::DSL::PlatformIntrospection, and Chef::DSL::DataQuery.
- #
- # This module includes both PlatformIntrospection and DataQuery to provide
- # the same interfaces and behavior as the prior Mixin::Language.
- #
- # This module is loaded via const_missing hook when Chef::Mixin::Language
- # is accessed. See chef/mixin/deprecation for details.
- module DeprecatedLanguageModule
-
- include Chef::DSL::PlatformIntrospection
- include Chef::DSL::DataQuery
-
- end
-
- deprecate_constant(:Language, DeprecatedLanguageModule, <<-EOM)
-Chef::Mixin::Language is deprecated. Use either (or both)
-Chef::DSL::PlatformIntrospection or Chef::DSL::DataQuery instead.
-EOM
- end
-end
diff --git a/lib/chef/mixin/language_include_attribute.rb b/lib/chef/mixin/language_include_attribute.rb
deleted file mode 100644
index 7cb66dc272..0000000000
--- a/lib/chef/mixin/language_include_attribute.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/dsl/include_attribute"
-require "chef/mixin/deprecation"
-
-class Chef
- module Mixin
-
- # DEPRECATED: This is just here for compatibility, use
- # Chef::DSL::IncludeAttribute instead.
-
- deprecate_constant(:LanguageIncludeAttribute, Chef::DSL::IncludeAttribute, <<-EOM)
-Chef::Mixin::LanguageIncludeAttribute is deprecated. Use
-Chef::DSL::IncludeAttribute instead.
-EOM
-
- end
-end
diff --git a/lib/chef/mixin/language_include_recipe.rb b/lib/chef/mixin/language_include_recipe.rb
deleted file mode 100644
index 97e384c7c4..0000000000
--- a/lib/chef/mixin/language_include_recipe.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/dsl/include_recipe"
-require "chef/mixin/deprecation"
-
-class Chef
- module Mixin
-
- deprecate_constant(:LanguageIncludeRecipe, Chef::DSL::IncludeRecipe, <<-EOM)
-Chef::Mixin::LanguageIncludeRecipe is deprecated, use Chef::DSL::IncludeRecipe
-instead.
-EOM
-
- end
-end
diff --git a/lib/chef/mixin/openssl_helper.rb b/lib/chef/mixin/openssl_helper.rb
new file mode 100644
index 0000000000..f12a559097
--- /dev/null
+++ b/lib/chef/mixin/openssl_helper.rb
@@ -0,0 +1,119 @@
+#
+# Copyright:: Copyright 2013-2018, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class Chef
+ module Mixin
+ # various helpers for use with openssl. Currently used by the openssl_* resources
+ module OpenSSLHelper
+ def self.included(_base)
+ require "openssl" unless defined?(::OpenSSL)
+ end
+
+ # determine the key filename from the cert filename
+ # @param [String] cert_filename the path to the certfile
+ # @return [String] the path to the keyfile
+ def get_key_filename(cert_filename)
+ cert_file_path, cert_filename = ::File.split(cert_filename)
+ cert_filename = ::File.basename(cert_filename, ::File.extname(cert_filename))
+ cert_file_path + ::File::SEPARATOR + cert_filename + ".key"
+ end
+
+ # is the key length a valid key length
+ # @param [Integer] number
+ # @return [Boolean] is length valid
+ def key_length_valid?(number)
+ number >= 1024 && ( number & (number - 1) == 0 )
+ end
+
+ # validate a dhparam file from path
+ # @param [String] dhparam_pem_path the path to the pem file
+ # @return [Boolean] is the key valid
+ def dhparam_pem_valid?(dhparam_pem_path)
+ # Check if the dhparam.pem file exists
+ # Verify the dhparam.pem file contains a key
+ return false unless ::File.exist?(dhparam_pem_path)
+ dhparam = ::OpenSSL::PKey::DH.new File.read(dhparam_pem_path)
+ dhparam.params_ok?
+ end
+
+ # given either a key file path or key file content see if it's actually
+ # a private key
+ # @param [String] key_file the path to the keyfile or the key contents
+ # @param [String] key_password optional password to the keyfile
+ # @return [Boolean] is the key valid?
+ def priv_key_file_valid?(key_file, key_password = nil)
+ # if the file exists try to read the content
+ # if not assume we were passed the key and set the string to the content
+ key_content = ::File.exist?(key_file) ? File.read(key_file) : key_file
+
+ begin
+ key = ::OpenSSL::PKey::RSA.new key_content, key_password
+ rescue ::OpenSSL::PKey::RSAError
+ return false
+ end
+ key.private?
+ end
+
+ # generate a dhparam file
+ # @param [String] key_length the length of the key
+ # @param [Integer] generator the dhparam generator to use
+ # @return [OpenSSL::PKey::DH]
+ def gen_dhparam(key_length, generator)
+ raise ArgumentError, "Key length must be a power of 2 greater than or equal to 1024" unless key_length_valid?(key_length)
+ raise TypeError, "Generator must be an integer" unless generator.is_a?(Integer)
+
+ ::OpenSSL::PKey::DH.new(key_length, generator)
+ end
+
+ # generate an RSA private key given key length
+ # @param [Integer] key_length the key length of the private key
+ # @return [OpenSSL::PKey::DH]
+ def gen_rsa_priv_key(key_length)
+ raise ArgumentError, "Key length must be a power of 2 greater than or equal to 1024" unless key_length_valid?(key_length)
+
+ ::OpenSSL::PKey::RSA.new(key_length)
+ end
+
+ # generate pem format of the public key given a private key
+ # @param [String] priv_key either the contents of the private key or the path to the file
+ # @param [String] priv_key_password optional password for the private key
+ # @return [String] pem format of the public key
+ def gen_rsa_pub_key(priv_key, priv_key_password = nil)
+ # if the file exists try to read the content
+ # if not assume we were passed the key and set the string to the content
+ key_content = ::File.exist?(priv_key) ? File.read(priv_key) : priv_key
+ key = ::OpenSSL::PKey::RSA.new key_content, priv_key_password
+ key.public_key.to_pem
+ end
+
+ # generate a pem file given a cipher, key, an optional key_password
+ # @param [OpenSSL::PKey::RSA] rsa_key the private key object
+ # @param [String] key_password the password for the private key
+ # @param [String] key_cipher the cipher to use
+ # @return [String] pem contents
+ def encrypt_rsa_key(rsa_key, key_password, key_cipher)
+ raise TypeError, "rsa_key must be a Ruby OpenSSL::PKey::RSA object" unless rsa_key.is_a?(::OpenSSL::PKey::RSA)
+ raise TypeError, "key_password must be a string" unless key_password.is_a?(String)
+ raise TypeError, "key_cipher must be a string" unless key_cipher.is_a?(String)
+ raise ArgumentError, "Specified key_cipher is not available on this system" unless ::OpenSSL::Cipher.ciphers.include?(key_cipher)
+
+ cipher = ::OpenSSL::Cipher.new(key_cipher)
+ rsa_key.to_pem(cipher, key_password)
+ end
+ end
+ end
+end
diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb
index d90e38b916..c955dd3b12 100644
--- a/lib/chef/mixin/params_validate.rb
+++ b/lib/chef/mixin/params_validate.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,6 +35,8 @@ class Chef
# map options are:
#
# @param opts [Hash<Symbol,Object>] Validation opts.
+ # @option opts [String] :validation_message A custom message to return
+ # should validation fail.
# @option opts [Object,Array] :is An object, or list of
# objects, that must match the value using Ruby's `===` operator
# (`opts[:is].any? { |v| v === value }`). (See #_pv_is.)
@@ -91,16 +93,20 @@ class Chef
raise ArgumentError, "Options must be a hash" unless opts.kind_of?(Hash)
raise ArgumentError, "Validation Map must be a hash" unless map.kind_of?(Hash)
+ @validation_message ||= {}
+
map.each do |key, validation|
unless key.kind_of?(Symbol) || key.kind_of?(String)
raise ArgumentError, "Validation map keys must be symbols or strings!"
end
+
case validation
when true
_pv_required(opts, key)
when false
true
when Hash
+ @validation_message[key] = validation.delete(:validation_message) if validation.has_key?(:validation_message)
validation.each do |check, carg|
check_method = "_pv_#{check}"
if respond_to?(check_method, true)
@@ -129,6 +135,10 @@ class Chef
validation.has_key?(:is) && _pv_is({ key => nil }, key, validation[:is], raise_error: false)
end
+ def _validation_message(key, default)
+ @validation_message.has_key?(key) ? @validation_message[key] : default
+ end
+
# Return the value of a parameter, or nil if it doesn't exist.
def _pv_opts_lookup(opts, key)
if opts.has_key?(key.to_s)
@@ -145,7 +155,7 @@ class Chef
if is_required
return true if opts.has_key?(key.to_s) && (explicitly_allows_nil || !opts[key.to_s].nil?)
return true if opts.has_key?(key.to_sym) && (explicitly_allows_nil || !opts[key.to_sym].nil?)
- raise Exceptions::ValidationFailed, "Required argument #{key.inspect} is missing!"
+ raise Exceptions::ValidationFailed, _validation_message(key, "Required argument #{key.inspect} is missing!")
end
true
end
@@ -168,7 +178,7 @@ class Chef
to_be.each do |tb|
return true if value == tb
end
- raise Exceptions::ValidationFailed, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}."
+ raise Exceptions::ValidationFailed, _validation_message(key, "Option #{key} must be equal to one of: #{to_be.join(", ")}! You passed #{value.inspect}.")
end
end
@@ -187,7 +197,7 @@ class Chef
to_be.each do |tb|
return true if value.kind_of?(tb)
end
- raise Exceptions::ValidationFailed, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}."
+ raise Exceptions::ValidationFailed, _validation_message(key, "Option #{key} must be a kind of #{to_be}! You passed #{value.inspect}.")
end
end
@@ -202,7 +212,7 @@ class Chef
unless value.nil?
Array(method_name_list).each do |method_name|
unless value.respond_to?(method_name)
- raise Exceptions::ValidationFailed, "Option #{key} must have a #{method_name} method!"
+ raise Exceptions::ValidationFailed, _validation_message(key, "Option #{key} must have a #{method_name} method!")
end
end
end
@@ -234,7 +244,7 @@ class Chef
if value.respond_to?(predicate_method)
if value.send(predicate_method)
- raise Exceptions::ValidationFailed, "Option #{key} cannot be #{predicate_method_base_name}"
+ raise Exceptions::ValidationFailed, _validation_message(key, "Option #{key} cannot be #{predicate_method_base_name}")
end
end
end
@@ -294,7 +304,7 @@ class Chef
Array(regex).flatten.each do |r|
return true if r.match(value.to_s)
end
- raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}"
+ raise Exceptions::ValidationFailed, _validation_message(key, "Option #{key}'s value #{value} does not match regular expression #{regex.inspect}")
end
end
@@ -316,7 +326,7 @@ class Chef
if !value.nil?
callbacks.each do |message, zeproc|
unless zeproc.call(value)
- raise Exceptions::ValidationFailed, "Option #{key}'s value #{value} #{message}!"
+ raise Exceptions::ValidationFailed, _validation_message(key, "Option #{key}'s value #{value} #{message}!")
end
end
end
@@ -428,7 +438,7 @@ class Chef
unless errors.empty?
message << " Errors:\n#{errors.map { |m| "- #{m}" }.join("\n")}"
end
- raise Exceptions::ValidationFailed, message
+ raise Exceptions::ValidationFailed, _validation_message(key, message)
end
end
diff --git a/lib/chef/mixin/powershell_out.rb b/lib/chef/mixin/powershell_out.rb
index ab7cf00a72..1a757074c2 100644
--- a/lib/chef/mixin/powershell_out.rb
+++ b/lib/chef/mixin/powershell_out.rb
@@ -74,7 +74,7 @@ class Chef
# Helper to build a powershell command around the script to run.
#
# @param script [String] script to run
- # @retrurn [String] powershell command to execute
+ # @return [String] powershell command to execute
def build_powershell_command(script)
flags = [
# Hides the copyright banner at startup.
diff --git a/lib/chef/mixin/properties.rb b/lib/chef/mixin/properties.rb
index 8ff2cc4501..6b95b87063 100644
--- a/lib/chef/mixin/properties.rb
+++ b/lib/chef/mixin/properties.rb
@@ -75,6 +75,8 @@ class Chef
# will return if the user does not set one. If this is `lazy`, it will
# be run in the context of the instance (and able to access other
# properties).
+ # @option options [String] :description A description of the property.
+ # @option options [String] :introduced The release that introduced this property
# @option options [Boolean] :desired_state `true` if this property is
# part of desired state. Defaults to `true`.
# @option options [Boolean] :identity `true` if this property
@@ -301,6 +303,17 @@ class Chef
raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property
property.reset(self)
end
+
+ #
+ # The description of the property
+ #
+ # @param name [Symbol] The name of the property.
+ # @return [String] The description of the property.
+ def property_description(name)
+ property = self.class.properties[name.to_sym]
+ raise ArgumentError, "Property #{name} is not defined in class #{self}" if !property
+ property.description
+ end
end
end
end
diff --git a/lib/chef/mixin/provides.rb b/lib/chef/mixin/provides.rb
index 43a726de8c..ca045d019e 100644
--- a/lib/chef/mixin/provides.rb
+++ b/lib/chef/mixin/provides.rb
@@ -4,7 +4,7 @@ require "chef/mixin/descendants_tracker"
class Chef
module Mixin
module Provides
- # TODO no longer needed, remove or deprecate?
+ # @todo no longer needed, remove or deprecate?
include Chef::Mixin::DescendantsTracker
def provides(short_name, opts = {})
@@ -12,7 +12,8 @@ class Chef
end
# Check whether this resource provides the resource_name DSL for the given
- # node. TODO remove this when we stop checking unregistered things.
+ # node.
+ # @todo remove this when we stop checking unregistered things.
# FIXME: yard with @yield
def provides?(node, resource)
raise NotImplementedError, :provides?
diff --git a/lib/chef/mixin/recipe_definition_dsl_core.rb b/lib/chef/mixin/recipe_definition_dsl_core.rb
deleted file mode 100644
index 6a9b12d31a..0000000000
--- a/lib/chef/mixin/recipe_definition_dsl_core.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-#--
-# Author:: Adam Jacob (<adam@chef.io>)
-# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-###
-# NOTE: This file and constant are here only for backwards compatibility.
-# New code should use Chef::DSL::Recipe instead.
-#
-# This constant (module name) will eventually be deprecated and then removed.
-###
-
-require "chef/mixin/deprecation"
-
-class Chef
- module Mixin
- deprecate_constant(:RecipeDefinitionDSLCore, Chef::DSL::Recipe, <<-EOM)
-Chef::Mixin::RecipeDefinitionDSLCore is deprecated. Use Chef::DSL::Recipe instead.
-EOM
- end
-end
diff --git a/lib/chef/mixin/securable.rb b/lib/chef/mixin/securable.rb
index 85c9dea1d4..788b236d94 100644
--- a/lib/chef/mixin/securable.rb
+++ b/lib/chef/mixin/securable.rb
@@ -59,17 +59,14 @@ class Chef
)
end
- #==WindowsMacros
# Defines methods for adding attributes to a chef resource to describe
# Windows file security metadata.
#
# This module is meant to be used to extend a class (instead of
# `include`-ing). A class is automatically extended with this module when
# it includes WindowsSecurableAttributes.
- # --
- # TODO should this be separated into different files?
+ # @todo should this be separated into different files?
module WindowsMacros
- # === rights_attribute
# "meta-method" for dynamically creating rights attributes on resources.
#
# Multiple rights attributes can be declared. This enables resources to
@@ -162,7 +159,6 @@ class Chef
end
end
- #==WindowsSecurableAttributes
# Defines #inherits to describe Windows file security ACLs on the
# including class
module WindowsSecurableAttributes
diff --git a/lib/chef/mixin/shell_out.rb b/lib/chef/mixin/shell_out.rb
index b6e4cffe92..57d5be4adc 100644
--- a/lib/chef/mixin/shell_out.rb
+++ b/lib/chef/mixin/shell_out.rb
@@ -131,7 +131,7 @@ class Chef
cmd
end
- # Helper for sublcasses to convert an array of string args into a string. It
+ # Helper for subclasses to convert an array of string args into a string. It
# will compact nil or empty strings in the array and will join the array elements
# with spaces, without introducing any double spaces for nil/empty elements.
#
@@ -143,7 +143,7 @@ class Chef
args.flatten.reject { |i| i.nil? || i == "" }.map(&:to_s).join(" ")
end
- # Helper for sublcasses to reject nil out of an array. It allows
+ # Helper for subclasses 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).
#
diff --git a/lib/chef/mixin/template.rb b/lib/chef/mixin/template.rb
index b10e036c4e..bb811aa758 100644
--- a/lib/chef/mixin/template.rb
+++ b/lib/chef/mixin/template.rb
@@ -23,7 +23,6 @@ class Chef
module Mixin
module Template
- # == ChefContext
# ChefContext was previously used to mix behavior into Erubis::Context so
# that it would be available to templates. This behavior has now moved to
# TemplateContext, but this module is still mixed in to the
@@ -32,7 +31,6 @@ class Chef
module ChefContext
end
- # == TemplateContext
# TemplateContext is the base context class for all templates in Chef. It
# defines user-facing extensions to the base Erubis::Context to provide
# enhanced features. Individual instances of TemplateContext can be
@@ -72,7 +70,7 @@ class Chef
# @return [String] recipe path
attr_reader :recipe_path
- # line in the recipe containing the template reosurce, e.g.:
+ # line in the recipe containing the template resource, e.g.:
# 2
#
# @return [String] recipe line
diff --git a/lib/chef/mixin/user_context.rb b/lib/chef/mixin/user_context.rb
index 40a72912a3..f5c2da1389 100644
--- a/lib/chef/mixin/user_context.rb
+++ b/lib/chef/mixin/user_context.rb
@@ -22,8 +22,11 @@ class Chef
module Mixin
module UserContext
- def with_user_context(user, password, domain = nil, &block)
- if node["platform_family"] != "windows"
+ # valid values for authentication => :remote, :local
+ # When authentication = :local, we use the credentials to create a logon session against the local system, and then try to access the files.
+ # When authentication = :remote, we continue with the current user but pass the provided credentials to the remote system.
+ def with_user_context(user, password, domain = nil, authentication = :remote, &block)
+ unless Chef::Platform.windows?
raise Exceptions::UnsupportedPlatform, "User context impersonation is supported only on the Windows platform"
end
@@ -31,11 +34,11 @@ class Chef
raise ArgumentError, "You must supply a block to `with_user_context`"
end
- login_session = nil
+ logon_session = nil
begin
if user
- logon_session = Chef::Util::Windows::LogonSession.new(user, password, domain)
+ logon_session = Chef::Util::Windows::LogonSession.new(user, password, domain, authentication)
logon_session.open
logon_session.set_user_context
end
diff --git a/lib/chef/mixin/why_run.rb b/lib/chef/mixin/why_run.rb
index ea62527bdd..b27458feae 100644
--- a/lib/chef/mixin/why_run.rb
+++ b/lib/chef/mixin/why_run.rb
@@ -21,7 +21,6 @@ class Chef
module Mixin
module WhyRun
- # ==ConvergeActions
# ConvergeActions implements the logic for why run. A ConvergeActions
# object wraps a collection of actions, which consist of a descriptive
# string and a block/Proc. Actions are executed by calling #converge!
@@ -60,7 +59,6 @@ class Chef
end
end
- # == ResourceRequirements
# ResourceRequirements provides a framework for making assertions about
# the host system's state. It also provides a mechanism for making
# assumptions about what the system's state might have been when running
@@ -182,7 +180,7 @@ class Chef
# will be allowed to continue in both whyrun and non-whyrun
# mode
#
- # With a service resource that requires /etc/init.d/service-name to exist:
+ # @example With a service resource that requires /etc/init.d/service-name to exist:
# # in a provider
# assert(:start, :restart) do |a|
# a.assertion { ::File.exist?("/etc/init.d/service-name") }
@@ -264,8 +262,8 @@ class Chef
# Define a new Assertion.
#
# Takes a list of action names for which the assertion should be made.
- # ==== Examples:
- # A File provider that requires the parent directory to exist:
+ #
+ # @example A File provider that requires the parent directory to exist:
#
# assert(:create, :create_if_missing) do |a|
# parent_dir = File.basename(@new_resource.path)
@@ -275,7 +273,7 @@ class Chef
# a.why_run("assuming parent directory #{parent_dir} would have been previously created"
# end
#
- # A service provider that requires the init script to exist:
+ # @example A service provider that requires the init script to exist:
#
# assert(:start, :restart) do |a|
# a.assertion { ::File.exist?(@new_resource.init_script) }
@@ -286,17 +284,14 @@ class Chef
# end
# end
#
- # A File provider that will error out if you don't have permissions do
- # delete the file, *even in why run mode*:
- #
+ # @example A File provider that will error out if you don't have permissions do delete the file, *even in why run mode*:
# assert(:delete) do |a|
# a.assertion { ::File.writable?(@new_resource.path) }
# a.failure_message(Exceptions::InsufficientPrivileges,
# "You don't have sufficient privileges to delete #{@new_resource.path}")
# end
#
- # A Template provider that will prevent action execution but continue the run in
- # whyrun mode if the template source is not available.
+ # @example A Template provider that will prevent action execution but continue the run in whyrun mode if the template source is not available.
# assert(:create, :create_if_missing) do |a|
# a.assertion { File::exist?(@new_resource.source) }
# a.failure_message Chef::Exceptions::TemplateError, "Template #{@new_resource.source} could not be found exist."
diff --git a/lib/chef/node.rb b/lib/chef/node.rb
index 549bde0dbb..7b530e1132 100644
--- a/lib/chef/node.rb
+++ b/lib/chef/node.rb
@@ -2,7 +2,7 @@
# Author:: Christopher Brown (<cb@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Tim Hinderliter (<tim@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,9 +47,7 @@ class Chef
def_delegators :attributes, :default_unless, :normal_unless, :override_unless, :set_unless
def_delegators :attributes, :read, :read!, :write, :write!, :unlink, :unlink!
- attr_accessor :recipe_list, :run_state, :override_runlist
-
- attr_accessor :chef_server_rest
+ attr_accessor :recipe_list, :run_state
# RunContext will set itself as run_context via this setter when
# initialized. This is needed so DSL::IncludeAttribute (in particular,
@@ -201,11 +199,6 @@ class Chef
attributes.normal
end
- def set
- 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
-
# Set a default of this node, but auto-vivify any Mashes that might
# be missing
def default
@@ -300,6 +293,7 @@ class Chef
@primary_runlist
end
+ attr_writer :override_runlist
def override_runlist(*args)
args.length > 0 ? @override_runlist.reset!(args) : @override_runlist
end
diff --git a/lib/chef/node/attribute.rb b/lib/chef/node/attribute.rb
index 2998866bb2..142150aeef 100644
--- a/lib/chef/node/attribute.rb
+++ b/lib/chef/node/attribute.rb
@@ -1,7 +1,7 @@
#--
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: AJ Christensen (<aj@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
# limitations under the License.
#
-require "chef/node/mixin/deep_merge_cache"
require "chef/node/mixin/immutablize_hash"
require "chef/node/mixin/state_tracking"
require "chef/node/immutable_collections"
@@ -45,7 +44,6 @@ class Chef
# expects. This include should probably be deleted?
include Enumerable
- include Chef::Node::Mixin::DeepMergeCache
include Chef::Node::Mixin::StateTracking
include Chef::Node::Mixin::ImmutablizeHash
@@ -187,6 +185,9 @@ class Chef
# return the automatic level attribute component
attr_reader :automatic
+ # return the immutablemash deep merge cache
+ attr_reader :deep_merge_cache
+
def initialize(normal, default, override, automatic, node = nil)
@default = VividMash.new(default, self, node, :default)
@env_default = VividMash.new({}, self, node, :env_default)
@@ -202,7 +203,8 @@ class Chef
@automatic = VividMash.new(automatic, self, node, :automatic)
- super(nil, self, node, :merged)
+ @deep_merge_cache = ImmutableMash.new({}, self, node, :merged)
+ @__node__ = node
end
# Debug what's going on with an attribute. +args+ is a path spec to the
@@ -226,6 +228,22 @@ class Chef
end
end
+ def reset
+ @deep_merge_cache = ImmutableMash.new({}, self, @__node__, :merged)
+ end
+
+ def reset_cache(*path)
+ if path.empty?
+ reset
+ else
+ container = read(*path)
+ case container
+ when Hash, Array
+ container.reset
+ end
+ end
+ end
+
# Set the cookbook level default attribute component to +new_data+.
def default=(new_data)
reset
@@ -290,7 +308,7 @@ class Chef
# clears attributes from all precedence levels
def rm(*args)
- with_deep_merged_return_value(self, *args) do
+ with_deep_merged_return_value(combined_all, *args) do
rm_default(*args)
rm_normal(*args)
rm_override(*args)
@@ -337,6 +355,9 @@ class Chef
def with_deep_merged_return_value(obj, *path, last)
hash = obj.read(*path)
return nil unless hash.is_a?(Hash)
+ # coerce from immutablemash/vividmash to plain-old Hash
+ # also de-immutablizes and dup's the return value correctly in chef-13
+ hash = hash.to_hash
ret = hash[last]
yield
ret
@@ -398,16 +419,16 @@ class Chef
# all of node['foo'] even if the user only requires node['foo']['bar']['baz'].
#
- def merged_attributes(*path)
- merge_all(path)
+ def combined_override(*path)
+ merge_overrides(path)
end
- def combined_override(*path)
- immutablize(merge_overrides(path))
+ def combined_all(*path)
+ path.empty? ? self : read(*path)
end
def combined_default(*path)
- immutablize(merge_defaults(path))
+ merge_defaults(path)
end
def normal_unless(*args)
@@ -425,11 +446,6 @@ class Chef
write(:override, *args) if override.read(*args[0...-1]).nil?
end
- def set_unless(*args)
- 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)
COMPONENTS.any? do |component_ivar|
instance_variable_get(component_ivar).has_key?(key)
@@ -476,6 +492,14 @@ class Chef
merged_attributes.to_s
end
+ def [](key)
+ @deep_merge_cache[key]
+ end
+
+ def merged_attributes
+ @deep_merge_cache
+ end
+
def inspect
"#<#{self.class} " << (COMPONENTS + [:@merged_attributes, :@properties]).map do |iv|
"#{iv}=#{instance_variable_get(iv).inspect}"
@@ -484,7 +508,14 @@ class Chef
private
- # Helper method for merge_all/merge_defaults/merge_overrides.
+ # For elements like Fixnums, true, nil...
+ def safe_dup(e)
+ e.dup
+ rescue TypeError
+ e
+ end
+
+ # Helper method for merge_defaults/merge_overrides.
#
# apply_path(thing, [ "foo", "bar", "baz" ]) = thing["foo"]["bar"]["baz"]
#
@@ -514,34 +545,6 @@ class Chef
end
end
- # For elements like Fixnums, true, nil...
- def safe_dup(e)
- e.dup
- rescue TypeError
- e
- end
-
- # Deep merge all attribute levels using hash-only merging between different precidence
- # levels (so override arrays completely replace arrays set at any default level).
- #
- # The path allows for selectively deep-merging a subtree of the node object.
- #
- # @param path [Array] Array of args to method chain to descend into the node object
- # @return [attr] Deep Merged values (may be VividMash, Hash, Array, etc) from the node object
- def merge_all(path)
- components = [
- merge_defaults(path),
- apply_path(@normal, path),
- merge_overrides(path),
- apply_path(@automatic, path),
- ]
-
- ret = components.inject(NIL) do |merged, component|
- hash_only_merge!(merged, component)
- end
- ret == NIL ? nil : ret
- end
-
# Deep merge the default attribute levels with array merging.
#
# The path allows for selectively deep-merging a subtree of the node object.
@@ -613,38 +616,6 @@ class Chef
end
end
- # @api private
- def hash_only_merge!(merge_onto, merge_with)
- # If there are two Hashes, recursively merge.
- if merge_onto.kind_of?(Hash) && merge_with.kind_of?(Hash)
- merge_with.each do |key, merge_with_value|
- value =
- if merge_onto.has_key?(key)
- hash_only_merge!(safe_dup(merge_onto[key]), merge_with_value)
- else
- merge_with_value
- end
-
- # internal_set bypasses converting keys, does convert values and allows writing to immutable mashes
- merge_onto.internal_set(key, value)
- end
- merge_onto
-
- # If merge_with is nil, don't replace merge_onto
- elsif merge_with.nil?
- merge_onto
-
- # In all other cases, replace merge_onto with merge_with
- else
- if merge_with.kind_of?(Hash)
- Chef::Node::ImmutableMash.new(merge_with)
- elsif merge_with.kind_of?(Array)
- Chef::Node::ImmutableArray.new(merge_with)
- else
- merge_with
- end
- end
- end
end
end
end
diff --git a/lib/chef/node/attribute_collections.rb b/lib/chef/node/attribute_collections.rb
index a31b2d2b9b..0271febea5 100644
--- a/lib/chef/node/attribute_collections.rb
+++ b/lib/chef/node/attribute_collections.rb
@@ -1,6 +1,6 @@
#--
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2012-2017, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -63,13 +63,13 @@ class Chef
MUTATOR_METHODS.each do |mutator|
define_method(mutator) do |*args, &block|
ret = super(*args, &block)
- send_reset_cache
+ send_reset_cache(__path__)
ret
end
end
def delete(key, &block)
- send_reset_cache(__path__, key)
+ send_reset_cache(__path__)
super
end
@@ -92,6 +92,7 @@ class Chef
private
def convert_value(value)
+ value.ensure_generated_cache! if value.respond_to?(:ensure_generated_cache!)
case value
when VividMash
value
@@ -147,13 +148,13 @@ class Chef
# object.
def delete(key, &block)
- send_reset_cache(__path__, key)
+ send_reset_cache(__path__)
super
end
MUTATOR_METHODS.each do |mutator|
define_method(mutator) do |*args, &block|
- send_reset_cache
+ send_reset_cache(__path__)
super(*args, &block)
end
end
@@ -174,8 +175,8 @@ class Chef
def []=(key, value)
ret = super
- send_reset_cache(__path__, key)
- ret
+ send_reset_cache(__path__)
+ ret # rubocop:disable Lint/Void
end
alias :attribute? :has_key?
@@ -189,6 +190,7 @@ class Chef
# AttrArray for consistency and to ensure that the added parts of the
# attribute tree will have the correct cache invalidation behavior.
def convert_value(value)
+ value.ensure_generated_cache! if value.respond_to?(:ensure_generated_cache!)
case value
when VividMash
value
diff --git a/lib/chef/node/common_api.rb b/lib/chef/node/common_api.rb
index a703c1ef54..fc0ffc57a5 100644
--- a/lib/chef/node/common_api.rb
+++ b/lib/chef/node/common_api.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright 2016, Chef Software, Inc.
+# Copyright:: Copyright 2016-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb
index 848e12d2df..dc8ead9176 100644
--- a/lib/chef/node/immutable_collections.rb
+++ b/lib/chef/node/immutable_collections.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright 2012-2017, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,22 +30,16 @@ class Chef
e
end
- def convert_value(value)
+ def convert_value(value, path = nil)
case value
when Hash
- ImmutableMash.new(value, __root__, __node__, __precedence__)
+ ImmutableMash.new({}, __root__, __node__, __precedence__, path)
when Array
- ImmutableArray.new(value, __root__, __node__, __precedence__)
- when ImmutableMash, ImmutableArray
- value
+ ImmutableArray.new([], __root__, __node__, __precedence__, path)
else
safe_dup(value).freeze
end
end
-
- def immutablize(value)
- convert_value(value)
- end
end
# == ImmutableArray
@@ -59,17 +53,51 @@ class Chef
# Chef::Node::Attribute's values, it overrides all reader methods to
# detect staleness and raise an error if accessed when stale.
class ImmutableArray < Array
+ alias_method :internal_clear, :clear
+ alias_method :internal_replace, :replace
+ alias_method :internal_push, :<<
+ alias_method :internal_to_a, :to_a
+ alias_method :internal_each, :each
+ private :internal_push, :internal_replace, :internal_clear, :internal_each
+ protected :internal_to_a
+
include Immutablize
- alias :internal_push :<<
- private :internal_push
+ methods = Array.instance_methods - Object.instance_methods +
+ [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ]
- def initialize(array_data = [])
- array_data.each do |value|
- internal_push(immutablize(value))
+ methods.each do |method|
+ define_method method do |*args, &block|
+ ensure_generated_cache!
+ super(*args, &block)
+ end
+ end
+
+ def each
+ ensure_generated_cache!
+ # aggressively pre generate the cache, works around ruby being too smart and fiddling with internals
+ internal_each { |i| i.ensure_generated_cache! if i.respond_to?(:ensure_generated_cache!) }
+ super
+ end
+
+ # because sometimes ruby gives us back Arrays or ImmutableArrays out of objects from things like #uniq or array slices
+ def return_normal_array(array)
+ if array.respond_to?(:internal_to_a, true)
+ array.internal_to_a
+ else
+ array.to_a
end
end
+ def uniq
+ ensure_generated_cache!
+ return_normal_array(super)
+ end
+
+ def initialize(array_data = [])
+ # Immutable collections no longer have initialized state
+ end
+
# For elements like Fixnums, true, nil...
def safe_dup(e)
e.dup
@@ -96,8 +124,81 @@ class Chef
alias_method :to_array, :to_a
+ def [](*args)
+ ensure_generated_cache!
+ args.length > 1 ? return_normal_array(super) : super # correctly handle array slices
+ end
+
+ def reset
+ @generated_cache = false
+ @short_circuit_attr_level = nil
+ internal_clear # redundant?
+ end
+
+ # @api private
+ def ensure_generated_cache!
+ generate_cache unless @generated_cache
+ @generated_cache = true
+ end
+
+ # This can be set to e.g. [ :@default ] by the parent container to cause this container
+ # to only use the default level and to bypass deep merging (the common case is either
+ # default-level or automatic-level and we aren't doing any deep merging). Right now it
+ # "optimized" for the case where we're no longer merging anything and only tracking a
+ # single level, and setting this to anything other than a size=1 array would behave
+ # in a broken fashion. That could be fixed, but the perf boost would likely not be
+ # that large in the typical case.
+ #
+ # @api private
+ attr_accessor :short_circuit_attr_levels
+
private
+ # deep merging of array attribute within normal and override where they are merged together
+ def combined_components(components)
+ combined_values = nil
+ components.each do |component|
+ values = __node__.attributes.instance_variable_get(component).read(*__path__)
+ next unless values.is_a?(Array)
+ @tracked_components << component
+ combined_values ||= []
+ combined_values += values
+ end
+ combined_values
+ end
+
+ def get_array(component)
+ array = __node__.attributes.instance_variable_get(component).read(*__path__)
+ if array.is_a?(Array)
+ @tracked_components << component
+ array
+ end # else nil
+ end
+
+ def generate_cache
+ internal_clear
+ components = []
+ @tracked_components = []
+ if short_circuit_attr_levels
+ components << get_array(short_circuit_attr_levels.first)
+ else
+ components << combined_components(Attribute::DEFAULT_COMPONENTS)
+ components << get_array(:@normal)
+ components << combined_components(Attribute::OVERRIDE_COMPONENTS)
+ components << get_array(:@automatic)
+ end
+ highest = components.compact.last
+ if highest.is_a?(Array)
+ internal_replace( highest.each_with_index.map { |x, i| convert_value(x, __path__ + [ i ] ) } )
+ end
+ if @tracked_components.size == 1
+ # tracked_components is accurate enough to tell us if we're not really merging
+ internal_each do |key, value|
+ value.short_circuit_attr_levels = @tracked_components if value.respond_to?(:short_circuit_attr_levels)
+ end
+ end
+ end
+
# needed for __path__
def convert_key(key)
key
@@ -120,19 +221,31 @@ class Chef
# it is stale.
# * Values can be accessed in attr_reader-like fashion via method_missing.
class ImmutableMash < Mash
+ alias_method :internal_clear, :clear
+ alias_method :internal_key?, :key? # FIXME: could bypass convert_key in Mash for perf
+ alias_method :internal_each, :each
+
include Immutablize
include CommonAPI
+ methods = Hash.instance_methods - Object.instance_methods +
+ [ :!, :!=, :<=>, :==, :===, :eql?, :to_s, :hash, :key, :has_key?, :inspect, :pretty_print, :pretty_print_inspect, :pretty_print_cycle, :pretty_print_instance_variables ]
+
+ methods.each do |method|
+ define_method method do |*args, &block|
+ ensure_generated_cache!
+ super(*args, &block)
+ end
+ end
+
# this is for deep_merge usage, chef users must never touch this API
# @api private
def internal_set(key, value)
- regular_writer(key, convert_value(value))
+ regular_writer(key, convert_value(value, __path__ + [ key ]))
end
def initialize(mash_data = {})
- mash_data.each do |key, value|
- internal_set(key, value)
- end
+ # Immutable collections no longer have initialized state
end
alias :attribute? :has_key?
@@ -168,11 +281,53 @@ class Chef
alias_method :to_hash, :to_h
- # For elements like Fixnums, true, nil...
- def safe_dup(e)
- e.dup
- rescue TypeError
- e
+ def [](key)
+ ensure_generated_cache!
+ super
+ end
+
+ def reset
+ @generated_cache = false
+ @short_circuit_attr_level = nil
+ internal_clear # redundant?
+ end
+
+ # @api private
+ def ensure_generated_cache!
+ generate_cache unless @generated_cache
+ @generated_cache = true
+ end
+
+ # @api private
+ attr_accessor :short_circuit_attr_levels
+
+ private
+
+ def generate_cache
+ internal_clear
+ components = short_circuit_attr_levels ? short_circuit_attr_levels : Attribute::COMPONENTS.reverse
+ # tracked_components is not entirely accurate due to the short-circuit
+ tracked_components = []
+ components.each do |component|
+ subhash = __node__.attributes.instance_variable_get(component).read(*__path__)
+ unless subhash.nil? # FIXME: nil is used for not present
+ tracked_components << component
+ if subhash.kind_of?(Hash)
+ subhash.each_key do |key|
+ next if internal_key?(key)
+ internal_set(key, subhash[key])
+ end
+ else
+ break
+ end
+ end
+ end
+ if tracked_components.size == 1
+ # tracked_components is accurate enough to tell us if we're not really merging
+ internal_each do |key, value|
+ value.short_circuit_attr_levels = tracked_components if value.respond_to?(:short_circuit_attr_levels)
+ end
+ end
end
prepend Chef::Node::Mixin::StateTracking
diff --git a/lib/chef/node/mixin/immutablize_array.rb b/lib/chef/node/mixin/immutablize_array.rb
index bd330cf8a9..88c7e6ffa9 100644
--- a/lib/chef/node/mixin/immutablize_array.rb
+++ b/lib/chef/node/mixin/immutablize_array.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright 2016-2017, Chef Software Inc.
+# Copyright:: Copyright 2016-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,15 +19,119 @@ class Chef
class Node
module Mixin
module ImmutablizeArray
+ # Allowed methods that MUST NOT mutate the object
+ # (if any of these methods mutate the underlying object that is a bug that needs to be fixed)
+ ALLOWED_METHODS = [
+ :&,
+ :*,
+ :+,
+ :-,
+ :[],
+ :abbrev,
+ :all?,
+ :any?,
+ :assoc,
+ :at,
+ :bsearch,
+ :bsearch_index,
+ :chunk,
+ :chunk_while,
+ :collect,
+ :collect_concat,
+ :combination,
+ :compact,
+ :count,
+ :cycle,
+ :detect,
+ :dig,
+ :drop,
+ :drop_while,
+ :each,
+ :each_cons,
+ :each_entry,
+ :each_index,
+ :each_slice,
+ :each_with_index,
+ :each_with_object,
+ :empty?,
+ :entries,
+ :fetch,
+ :find,
+ :find_all,
+ :find_index,
+ :first,
+ :flat_map,
+ :flatten,
+ :grep,
+ :grep_v,
+ :group_by,
+ :include?,
+ :index,
+ :inject,
+ :join,
+ :last,
+ :lazy,
+ :length,
+ :map,
+ :max,
+ :max_by,
+ :member?,
+ :min,
+ :min_by,
+ :minmax,
+ :minmax_by,
+ :none?,
+ :one?,
+ :pack,
+ :partition,
+ :permutation,
+ :product,
+ :rassoc,
+ :reduce,
+ :reject,
+ :repeated_combination,
+ :repeated_permutation,
+ :reverse,
+ :reverse_each,
+ :rindex,
+ :rotate,
+ :sample,
+ :save_plist,
+ :select,
+ :shelljoin,
+ :shuffle,
+ :size,
+ :slice,
+ :slice_after,
+ :slice_before,
+ :slice_when,
+ :sort,
+ :sort_by,
+ :sum,
+ :take,
+ :take_while,
+ :to_a,
+ :to_ary,
+ :to_h,
+ :to_plist,
+ :to_set,
+ :transpose,
+ :uniq,
+ :values_at,
+ :zip,
+ :|,
+ ]
# A list of methods that mutate Array. Each of these is overridden to
# raise an error, making this instances of this class more or less
# immutable.
DISALLOWED_MUTATOR_METHODS = [
:<<,
:[]=,
+ :append,
:clear,
:collect!,
:compact!,
+ :concat,
:default=,
:default_proc=,
:delete,
@@ -40,18 +144,21 @@ class Chef
:map!,
:merge!,
:pop,
+ :prepend,
:push,
- :update,
:reject!,
- :reverse!,
:replace,
+ :reverse!,
+ :rotate!,
:select!,
:shift,
+ :shuffle!,
:slice!,
:sort!,
:sort_by!,
:uniq!,
:unshift,
+ :update,
]
# Redefine all of the methods that mutate a Hash to raise an error when called.
diff --git a/lib/chef/node/mixin/immutablize_hash.rb b/lib/chef/node/mixin/immutablize_hash.rb
index f6b22ed7d7..cd2bbf7bf6 100644
--- a/lib/chef/node/mixin/immutablize_hash.rb
+++ b/lib/chef/node/mixin/immutablize_hash.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright 2016-2017, Chef Software Inc.
+# Copyright:: Copyright 2016-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,10 +19,112 @@ class Chef
class Node
module Mixin
module ImmutablizeHash
+ # allowed methods that MUST NOT mutate the object
+ # (if any of these methods mutate the underlying object that is a bug that needs to be fixed)
+ ALLOWED_METHODS = [
+ :<,
+ :<=,
+ :>,
+ :>=,
+ :[],
+ :all?,
+ :any?,
+ :assoc,
+ :chunk,
+ :chunk_while,
+ :collect,
+ :collect_concat,
+ :compact,
+ :compare_by_identity,
+ :compare_by_identity?,
+ :count,
+ :cycle,
+ :default,
+ :default_proc,
+ :detect,
+ :dig,
+ :drop,
+ :drop_while,
+ :each,
+ :each_cons,
+ :each_entry,
+ :each_key,
+ :each_pair,
+ :each_slice,
+ :each_value,
+ :each_with_index,
+ :each_with_object,
+ :empty?,
+ :entries,
+ :fetch,
+ :fetch_values,
+ :find,
+ :find_all,
+ :find_index,
+ :first,
+ :flat_map,
+ :flatten,
+ :grep,
+ :grep_v,
+ :group_by,
+ :has_key?,
+ :has_value?,
+ :include?,
+ :index,
+ :inject,
+ :invert,
+ :key,
+ :key?,
+ :keys,
+ :lazy,
+ :length,
+ :map,
+ :max,
+ :max_by,
+ :member?,
+ :merge,
+ :min,
+ :min_by,
+ :minmax,
+ :minmax_by,
+ :none?,
+ :one?,
+ :partition,
+ :rassoc,
+ :reduce,
+ :reject,
+ :reverse_each,
+ :save_plist,
+ :select,
+ :size,
+ :slice,
+ :slice_after,
+ :slice_before,
+ :slice_when,
+ :sort,
+ :sort_by,
+ :sum,
+ :take,
+ :take_while,
+ :to_a,
+ :to_h,
+ :to_hash,
+ :to_plist,
+ :to_proc,
+ :to_set,
+ :transform_keys,
+ :transform_values,
+ :uniq,
+ :value?,
+ :values,
+ :values_at,
+ :zip,
+ ]
DISALLOWED_MUTATOR_METHODS = [
:[]=,
:clear,
:collect!,
+ :compact!,
:default=,
:default_proc=,
:delete,
@@ -30,15 +132,19 @@ class Chef
:keep_if,
:map!,
:merge!,
- :update,
+ :rehash,
:reject!,
:replace,
:select!,
:shift,
- :write,
- :write!,
- :unlink,
+ :store,
+ :transform_keys!,
+ :transform_values!,
:unlink!,
+ :unlink,
+ :update,
+ :write!,
+ :write,
]
# Redefine all of the methods that mutate a Hash to raise an error when called.
diff --git a/lib/chef/node/mixin/state_tracking.rb b/lib/chef/node/mixin/state_tracking.rb
index 5958973024..0c3d4c33a4 100644
--- a/lib/chef/node/mixin/state_tracking.rb
+++ b/lib/chef/node/mixin/state_tracking.rb
@@ -1,5 +1,5 @@
#--
-# Copyright:: Copyright 2016, Chef Software, Inc.
+# Copyright:: Copyright 2016-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,11 +24,12 @@ class Chef
attr_reader :__node__
attr_reader :__precedence__
- def initialize(data = nil, root = self, node = nil, precedence = nil)
+ def initialize(data = nil, root = self, node = nil, precedence = nil, path = nil)
# __path__ and __root__ must be nil when we call super so it knows
# to avoid resetting the cache on construction
data.nil? ? super() : super(data)
- @__path__ = []
+ @__path__ = path
+ @__path__ ||= []
@__root__ = root
@__node__ = node
@__precedence__ = precedence
@@ -76,9 +77,8 @@ class Chef
end
end
- def send_reset_cache(path = nil, key = nil)
- next_path = [ path, key ].flatten.compact
- __root__.reset_cache(next_path.first) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !next_path.nil?
+ def send_reset_cache(path)
+ __root__.reset_cache(*path) if !__root__.nil? && __root__.respond_to?(:reset_cache) && !path.nil?
end
def copy_state_to(ret, next_path)
diff --git a/lib/chef/node_map.rb b/lib/chef/node_map.rb
index 7a1a09ae24..ecd5c9df8f 100644
--- a/lib/chef/node_map.rb
+++ b/lib/chef/node_map.rb
@@ -1,6 +1,6 @@
#
# Author:: Lamont Granquist (<lamont@chef.io>)
-# Copyright:: Copyright 2014-2017, Chef Software Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,6 +16,25 @@
# limitations under the License.
#
+#
+# example of a NodeMap entry for the user resource (as typed on the DSL):
+#
+# :user=>
+# [{:klass=>Chef::Resource::User::AixUser, :os=>"aix"},
+# {:klass=>Chef::Resource::User::DsclUser, :os=>"darwin"},
+# {:klass=>Chef::Resource::User::PwUser, :os=>"freebsd"},
+# {:klass=>Chef::Resource::User::LinuxUser, :os=>"linux"},
+# {:klass=>Chef::Resource::User::SolarisUser,
+# :os=>["omnios", "solaris2"]},
+# {:klass=>Chef::Resource::User::WindowsUser, :os=>"windows"}],
+#
+# the entries in the array are pre-sorted into priority order (blocks/platform_version/platform/platform_family/os/none) so that
+# the first entry's :klass that matches the filter is returned when doing a get.
+#
+# note that as this examples show filter values may be a scalar string or an array of scalar strings.
+#
+# XXX: confusingly, in the *_priority_map the :klass may be an array of Strings of class names
+#
class Chef
class NodeMap
@@ -31,13 +50,12 @@ class Chef
#
# @return [NodeMap] Returns self for possible chaining
#
- def set(key, value, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block)
- filters = {}
- filters[:platform] = platform if platform
- filters[:platform_version] = platform_version if platform_version
- filters[:platform_family] = platform_family if platform_family
- filters[:os] = os if os
- new_matcher = { value: value, filters: filters }
+ def set(key, klass, platform: nil, platform_version: nil, platform_family: nil, os: nil, canonical: nil, override: nil, &block)
+ new_matcher = { klass: klass }
+ new_matcher[:platform] = platform if platform
+ new_matcher[:platform_version] = platform_version if platform_version
+ new_matcher[:platform_family] = platform_family if platform_family
+ new_matcher[:os] = os if os
new_matcher[:block] = block if block
new_matcher[:canonical] = canonical if canonical
new_matcher[:override] = override if override
@@ -48,7 +66,10 @@ class Chef
map[key] ||= []
map[key].each_with_index do |matcher, index|
cmp = compare_matchers(key, new_matcher, matcher)
- insert_at ||= index if cmp && cmp <= 0
+ if cmp && cmp <= 0
+ insert_at = index
+ break
+ end
end
if insert_at
map[key].insert(insert_at, new_matcher)
@@ -68,11 +89,14 @@ class Chef
# @param canonical [Boolean] `true` or `false` to match canonical or
# non-canonical values only. `nil` to ignore canonicality. Default: `nil`
#
- # @return [Object] Value
+ # @return [Object] Class
#
def get(node, key, canonical: nil)
- raise ArgumentError, "first argument must be a Chef::Node" unless node.is_a?(Chef::Node) || node.nil?
- list(node, key, canonical: canonical).first
+ return nil unless map.has_key?(key)
+ map[key].map do |matcher|
+ return matcher[:klass] if node_matches?(node, matcher) && canonical_matches?(canonical, matcher)
+ end
+ nil
end
#
@@ -85,23 +109,22 @@ class Chef
# @param canonical [Boolean] `true` or `false` to match canonical or
# non-canonical values only. `nil` to ignore canonicality. Default: `nil`
#
- # @return [Object] Value
+ # @return [Object] Class
#
def list(node, key, canonical: nil)
- raise ArgumentError, "first argument must be a Chef::Node" unless node.is_a?(Chef::Node) || node.nil?
return [] unless map.has_key?(key)
map[key].select do |matcher|
node_matches?(node, matcher) && canonical_matches?(canonical, matcher)
- end.map { |matcher| matcher[:value] }
+ end.map { |matcher| matcher[:klass] }
end
# Seriously, don't use this, it's nearly certain to change on you
# @return remaining
# @api private
- def delete_canonical(key, value)
+ def delete_canonical(key, klass)
remaining = map[key]
if remaining
- remaining.delete_if { |matcher| matcher[:canonical] && Array(matcher[:value]) == Array(value) }
+ remaining.delete_if { |matcher| matcher[:canonical] && Array(matcher[:klass]) == Array(klass) }
if remaining.empty?
map.delete(key)
remaining = nil
@@ -143,7 +166,7 @@ class Chef
filter_values.empty? ||
Array(filter_values).any? do |v|
- Chef::VersionConstraint::Platform.new(v).include?(value)
+ Gem::Requirement.new(v).satisfied_by?(Gem::Version.new(value))
end
end
@@ -161,7 +184,7 @@ class Chef
def node_matches?(node, matcher)
return true if !node
- filters_match?(node, matcher[:filters]) && block_matches?(node, matcher[:block])
+ filters_match?(node, matcher) && block_matches?(node, matcher[:block])
end
def canonical_matches?(canonical, matcher)
@@ -169,63 +192,40 @@ class Chef
!!canonical == !!matcher[:canonical]
end
- # @api private
- def dispatch_compare_matchers(key, new_matcher, matcher)
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:block] }
+ #
+ # "provides" lines with identical filters sort by class name (ascending).
+ #
+ def compare_matchers(key, new_matcher, matcher)
+ cmp = compare_matcher_properties(new_matcher[:block], matcher[:block])
return cmp if cmp != 0
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_version] }
+ cmp = compare_matcher_properties(new_matcher[:platform_version], matcher[:platform_version])
return cmp if cmp != 0
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform] }
+ cmp = compare_matcher_properties(new_matcher[:platform], matcher[:platform])
return cmp if cmp != 0
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:platform_family] }
+ cmp = compare_matcher_properties(new_matcher[:platform_family], matcher[:platform_family])
return cmp if cmp != 0
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:filters][:os] }
+ cmp = compare_matcher_properties(new_matcher[:os], matcher[:os])
return cmp if cmp != 0
- cmp = compare_matcher_properties(new_matcher, matcher) { |m| m[:override] }
+ cmp = compare_matcher_properties(new_matcher[:override], matcher[:override])
return cmp if cmp != 0
# If all things are identical, return 0
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)
+ def compare_matcher_properties(a, b)
+ # falsity comparisons here handle both "nil" and "false"
+ return 1 if !a && b
+ return -1 if !b && a
+ return 0 if !a && !b
- # Check for blcacklists ('!windows'). Those always come *after* positive
+ # Check for blacklists ('!windows'). Those always come *after* positive
# whitelists.
a_negated = Array(a).any? { |f| f.is_a?(String) && f.start_with?("!") }
b_negated = Array(b).any? { |f| f.is_a?(String) && f.start_with?("!") }
- if a_negated != b_negated
- return 1 if a_negated
- return -1 if b_negated
- end
+ return 1 if a_negated && !b_negated
+ return -1 if b_negated && !a_negated
- # We treat false / true and nil / not-nil with the same comparison
- a = nil if a == false
- b = nil if b == false
- cmp = a <=> b
- # This is the case where one is non-nil, and one is nil. The one that is
- # nil is "greater" (i.e. it should come last).
- if cmp.nil?
- return 1 if a.nil?
- return -1 if b.nil?
- end
- cmp
+ a <=> b
end
def map
diff --git a/lib/chef/platform/rebooter.rb b/lib/chef/platform/rebooter.rb
index 33a6e24be2..430d175869 100644
--- a/lib/chef/platform/rebooter.rb
+++ b/lib/chef/platform/rebooter.rb
@@ -33,14 +33,18 @@ class Chef
def reboot!(node)
reboot_info = node.run_context.reboot_info
- cmd = if Chef::Platform.windows?
+ cmd = case
+ when Chef::Platform.windows?
# should this do /f as well? do we then need a minimum delay to let apps quit?
# 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]}\""
+ when node["os"] == "solaris2"
+ # SysV-flavored shutdown
+ "shutdown -i6 -g#{reboot_info[:delay_mins]} -y \"#{reboot_info[:reason]}\" &"
else
- # probably Linux-only.
- "shutdown -r +#{reboot_info[:delay_mins]} \"#{reboot_info[:reason]}\""
+ # Linux/BSD/Mac/AIX and other systems with BSD-ish shutdown
+ "shutdown -r +#{reboot_info[:delay_mins]} \"#{reboot_info[:reason]}\" &"
end
msg = "Rebooting server at a recipe's request. Details: #{reboot_info.inspect}"
diff --git a/lib/chef/property.rb b/lib/chef/property.rb
index a72e41a61e..be54c8bfa1 100644
--- a/lib/chef/property.rb
+++ b/lib/chef/property.rb
@@ -60,10 +60,12 @@ class Chef
# options).
# @option options [Symbol] :name The name of this property.
# @option options [Class] :declared_in The class this property comes from.
+ # @option options [String] :description A description of the property.
# @option options [Symbol] :instance_variable_name The instance variable
# tied to this property. Must include a leading `@`. Defaults to `@<name>`.
# `nil` means the property is opaque and not tied to a specific instance
# variable.
+ # @option options [String] :introduced The release that introduced this property
# @option options [Boolean] :desired_state `true` if this property is part of desired
# state. Defaults to `true`.
# @option options [Boolean] :identity `true` if this property is part of object
@@ -99,7 +101,7 @@ class Chef
if options.has_key?(:name_attribute)
# If we have both name_attribute and name_property and they differ, raise an error
if options.has_key?(:name_property)
- raise ArgumentError, "Cannot specify both name_property and name_attribute together on property #{self}."
+ raise ArgumentError, "name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property #{self}"
end
# replace name_property with name_attribute in place
options = Hash[options.map { |k, v| k == :name_attribute ? [ :name_property, v ] : [ k, v ] }]
@@ -107,7 +109,7 @@ class Chef
end
if options.has_key?(:default) && options.has_key?(:name_property)
- raise ArgumentError, "Cannot specify both default and name_property/name_attribute together on property #{self}"
+ raise ArgumentError, "A property cannot be both a name_property/name_attribute and have a default value. Use one or the other on property #{self}"
end
# Recursively freeze the default if it isn't a lazy value.
@@ -158,6 +160,24 @@ class Chef
end
#
+ # A description of this property.
+ #
+ # @return [String]
+ #
+ def description
+ options[:description]
+ end
+
+ #
+ # When this property was introduced
+ #
+ # @return [String]
+ #
+ def introduced
+ options[:introduced]
+ end
+
+ #
# The instance variable associated with this property.
#
# Defaults to `@<name>`
@@ -252,7 +272,7 @@ class Chef
#
def validation_options
@validation_options ||= options.reject do |k, v|
- [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive].include?(k)
+ [:declared_in, :name, :instance_variable_name, :desired_state, :identity, :default, :name_property, :coerce, :required, :nillable, :sensitive, :description, :introduced].include?(k)
end
end
@@ -361,7 +381,7 @@ class Chef
end
if value.nil? && required?
- raise Chef::Exceptions::ValidationFailed, "#{name} is required"
+ raise Chef::Exceptions::ValidationFailed, "#{name} is a required property"
else
value
end
@@ -386,7 +406,7 @@ class Chef
value = set_value(resource, input_to_stored_value(resource, value))
if value.nil? && required?
- raise Chef::Exceptions::ValidationFailed, "#{name} is required"
+ raise Chef::Exceptions::ValidationFailed, "#{name} is a required property"
else
value
end
@@ -457,7 +477,7 @@ class Chef
# options.
#
# @param resource [Chef::Resource] The resource we're validating against
- # (to provide context for the validate).
+ # (to provide context for the validation).
# @param value The value to validate.
#
# @raise Chef::Exceptions::ValidationFailed If the value is invalid for
@@ -514,18 +534,18 @@ class Chef
# very confusing results.
if property_redefines_method?
resource_name = declared_in.respond_to?(:resource_name) ? declared_in.resource_name : declared_in
- raise ArgumentError, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method."
+ raise ArgumentError, "Property `#{name}` of resource `#{resource_name}` overwrites an existing method. A different name should be used for this property."
end
# 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
def #{name}(value=NOT_PASSED)
- raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
+ raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
self.class.properties[#{name.inspect}].call(self, value)
end
def #{name}=(value)
- raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
+ raise "Property `#{name}` of `\#{self}` was incorrectly passed a block. Possible property-resource collision. To call a resource named `#{name}` either rename the property or else use `declare_resource(:#{name}, ...)`" if block_given?
self.class.properties[#{name.inspect}].set(self, value)
end
EOM
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 1ebdfa6feb..7cb2301772 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
-# Copyright:: Copyright 2008-2016, 2009-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2016, 2009-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,7 +38,6 @@ class Chef
attr_accessor :run_context
attr_reader :recipe_name
- attr_reader :cookbook_name
include Chef::Mixin::WhyRun
extend Chef::Mixin::Provides
@@ -198,6 +197,20 @@ class Chef
@requirements ||= ResourceRequirements.new(@new_resource, run_context)
end
+ def description(description = "NOT_PASSED")
+ if description != "NOT_PASSED"
+ @description = description
+ end
+ @description
+ end
+
+ def introduced(introduced = "NOT_PASSED")
+ if introduced != "NOT_PASSED"
+ @introduced = introduced
+ end
+ @introduced
+ end
+
def converge_by(descriptions, &block)
converge_actions.add_action(descriptions, &block)
end
@@ -250,7 +263,13 @@ class Chef
properties_str = if new_resource.sensitive
specified_properties.join(", ")
else
- specified_properties.map { |p| "#{p}=#{new_resource.send(p).inspect}" }.join(", ")
+ specified_properties.map do |property|
+ "#{property}=" << if new_resource.class.properties[property].sensitive?
+ "(suppressed sensitive property)"
+ else
+ new_resource.send(property).inspect
+ end
+ end.join(", ")
end
Chef::Log.debug("Skipping update of #{new_resource}: has not changed any of the specified properties #{properties_str}.")
return false
@@ -259,7 +278,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 new_resource.sensitive
+ properties_str = if new_resource.sensitive || new_resource.class.properties[p].sensitive?
"(suppressed sensitive property)"
else
"#{new_resource.send(p).inspect} (was #{current_resource.send(p).inspect})"
@@ -274,7 +293,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 new_resource.sensitive
+ properties_str = if new_resource.sensitive || new_resource.class.properties[property].sensitive?
"(suppressed sensitive property)"
else
new_resource.send(property).inspect
@@ -325,7 +344,7 @@ class Chef
define_singleton_method(:inspect) { to_s }
# Add a delegator for each explicit property that will get the *current* value
# of the property by default instead of the *actual* value.
- resource.class.properties.each do |name, property|
+ resource.class.properties.each_key do |name|
class_eval(<<-EOM, __FILE__, __LINE__)
def #{name}(*args, &block)
# If no arguments were passed, we process "get" by defaulting
diff --git a/lib/chef/provider/apt_preference.rb b/lib/chef/provider/apt_preference.rb
index ff4ea02ff0..59c6fc7f6d 100644
--- a/lib/chef/provider/apt_preference.rb
+++ b/lib/chef/provider/apt_preference.rb
@@ -24,7 +24,7 @@ require "chef/log"
class Chef
class Provider
class AptPreference < Chef::Provider
- provides :apt_preference, os: "linux", platform_family: "debian"
+ provides :apt_preference, platform_family: "debian"
APT_PREFERENCE_DIR = "/etc/apt/preferences.d".freeze
diff --git a/lib/chef/provider/apt_repository.rb b/lib/chef/provider/apt_repository.rb
index 2d86a6fce4..c16f1e5767 100644
--- a/lib/chef/provider/apt_repository.rb
+++ b/lib/chef/provider/apt_repository.rb
@@ -27,7 +27,7 @@ class Chef
class AptRepository < Chef::Provider
include Chef::Mixin::ShellOut
- provides :apt_repository, os: "linux", platform_family: "debian"
+ provides :apt_repository, platform_family: "debian"
LIST_APT_KEYS = "apt-key list".freeze
LIST_APT_KEY_FINGERPRINTS = "apt-key adv --list-public-keys --with-fingerprint --with-colons".freeze
diff --git a/lib/chef/provider/apt_update.rb b/lib/chef/provider/apt_update.rb
index bfd9603e4e..9d794abcf0 100644
--- a/lib/chef/provider/apt_update.rb
+++ b/lib/chef/provider/apt_update.rb
@@ -23,7 +23,7 @@ require "chef/dsl/declare_resource"
class Chef
class Provider
class AptUpdate < Chef::Provider
- provides :apt_update, os: "linux", platform_family: "debian"
+ provides :apt_update, platform_family: "debian"
APT_CONF_DIR = "/etc/apt/apt.conf.d"
STAMP_DIR = "/var/lib/apt/periodic"
diff --git a/lib/chef/provider/deploy.rb b/lib/chef/provider/deploy.rb
deleted file mode 100644
index c4229d2441..0000000000
--- a/lib/chef/provider/deploy.rb
+++ /dev/null
@@ -1,470 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/mixin/from_file"
-require "chef/provider/git"
-require "chef/provider/subversion"
-require "chef/dsl/recipe"
-require "chef/util/path_helper"
-
-class Chef
- class Provider
- class Deploy < Chef::Provider
-
- include Chef::DSL::Recipe
- include Chef::Mixin::FromFile
-
- attr_reader :scm_provider, :release_path, :shared_path, :previous_release_path
-
- def initialize(new_resource, run_context)
- super(new_resource, run_context)
-
- # will resolve to either git or svn based on resource attributes,
- # and will create a resource corresponding to that provider
- @scm_provider = new_resource.scm_provider.new(new_resource, run_context)
-
- # @configuration is not used by Deploy, it is only for backwards compat with
- # chef-deploy or capistrano hooks that might use it to get environment information
- @configuration = new_resource.to_hash
- @configuration[:environment] = @configuration[:environment] && @configuration[:environment]["RAILS_ENV"]
- end
-
- def load_current_resource
- @scm_provider.load_current_resource
- @release_path = new_resource.deploy_to + "/releases/#{release_slug}"
- @shared_path = new_resource.shared_path
- end
-
- def sudo(command, &block)
- execute(command, &block)
- end
-
- def run(command, &block)
- exec = execute(command, &block)
- exec.user(new_resource.user) if new_resource.user
- exec.group(new_resource.group) if new_resource.group
- exec.cwd(release_path) unless exec.cwd
- exec.environment(new_resource.environment) unless exec.environment
- converge_by("execute #{command}") do
- exec
- end
- end
-
- def define_resource_requirements
- requirements.assert(:rollback) do |a|
- a.assertion { all_releases[-2] }
- a.failure_message(RuntimeError, "There is no release to rollback to!")
- #There is no reason to assume 2 deployments in a single chef run, hence fails in whyrun.
- end
-
- [ new_resource.before_migrate, new_resource.before_symlink,
- new_resource.before_restart, new_resource.after_restart ].each do |script|
- requirements.assert(:deploy, :force_deploy) do |a|
- callback_file = "#{release_path}/#{script}"
- a.assertion do
- if script && script.class == String
- ::File.exist?(callback_file)
- else
- true
- end
- end
- a.failure_message(RuntimeError, "Can't find your callback file #{callback_file}")
- a.whyrun("Would assume callback file #{callback_file} included in release")
- end
- end
- end
-
- def action_deploy
- save_release_state
- if deployed?(release_path )
- if current_release?(release_path )
- Chef::Log.debug("#{new_resource} is the latest version")
- else
- rollback_to release_path
- end
- else
-
- with_rollback_on_error do
- deploy
- end
- end
- end
-
- def action_force_deploy
- if deployed?(release_path)
- converge_by("delete deployed app at #{release_path} prior to force-deploy") do
- Chef::Log.info("Already deployed app at #{release_path}, forcing.")
- FileUtils.rm_rf(release_path)
- Chef::Log.info("#{new_resource} forcing deploy of already deployed app at #{release_path}")
- end
- end
-
- # Alternatives:
- # * Move release_path directory before deploy and move it back when error occurs
- # * Rollback to previous commit
- # * Do nothing - because deploy is force, it will be retried in short time
- # Because last is simplest, keep it
- deploy
- end
-
- def action_rollback
- rollback_to all_releases[-2]
- end
-
- def rollback_to(target_release_path)
- @release_path = target_release_path
-
- rp_index = all_releases.index(release_path)
- releases_to_nuke = all_releases[(rp_index + 1)..-1]
-
- rollback
-
- releases_to_nuke.each do |i|
- converge_by("roll back by removing release #{i}") do
- Chef::Log.info "#{new_resource} removing release: #{i}"
- FileUtils.rm_rf i
- end
- release_deleted(i)
- end
- end
-
- def deploy
- verify_directories_exist
- update_cached_repo # no converge-by - scm provider will dothis
- enforce_ownership
- copy_cached_repo
- install_gems
- enforce_ownership
- callback(:before_migrate, new_resource.before_migrate)
- migrate
- callback(:before_symlink, new_resource.before_symlink)
- symlink
- callback(:before_restart, new_resource.before_restart)
- restart
- callback(:after_restart, new_resource.after_restart)
- cleanup!
- Chef::Log.info "#{new_resource} deployed to #{new_resource.deploy_to}"
- end
-
- def rollback
- Chef::Log.info "#{new_resource} rolling back to previous release #{release_path}"
- symlink
- Chef::Log.info "#{new_resource} restarting with previous release"
- restart
- end
-
- def callback(what, callback_code = nil)
- @collection = Chef::ResourceCollection.new
- case callback_code
- when Proc
- Chef::Log.info "#{new_resource} running callback #{what}"
- recipe_eval(&callback_code)
- when String
- run_callback_from_file("#{release_path}/#{callback_code}")
- when nil
- run_callback_from_file("#{release_path}/deploy/#{what}.rb")
- end
- end
-
- def migrate
- run_symlinks_before_migrate
-
- if new_resource.migrate
- enforce_ownership
-
- environment = new_resource.environment
- env_info = environment && environment.map do |key_and_val|
- "#{key_and_val.first}='#{key_and_val.last}'"
- end.join(" ")
-
- converge_by("execute migration command #{new_resource.migration_command}") do
- Chef::Log.info "#{new_resource} migrating #{new_resource.user} with environment #{env_info}"
- shell_out!(new_resource.migration_command, run_options(:cwd => release_path, :log_level => :info))
- end
- end
- end
-
- def symlink
- purge_tempfiles_from_current_release
- link_tempfiles_to_current_release
- link_current_release_to_production
- Chef::Log.info "#{new_resource} updated symlinks"
- end
-
- def restart
- if restart_cmd = new_resource.restart_command
- if restart_cmd.kind_of?(Proc)
- Chef::Log.info("#{new_resource} restarting app with embedded recipe")
- recipe_eval(&restart_cmd)
- else
- converge_by("restart app using command #{new_resource.restart_command}") do
- Chef::Log.info("#{new_resource} restarting app")
- shell_out!(new_resource.restart_command, run_options(:cwd => new_resource.current_path))
- end
- end
- end
- end
-
- def cleanup!
- converge_by("update release history data") do
- release_created(release_path)
- end
-
- chop = -1 - new_resource.keep_releases
- all_releases[0..chop].each do |old_release|
- converge_by("remove old release #{old_release}") do
- Chef::Log.info "#{new_resource} removing old release #{old_release}"
- FileUtils.rm_rf(old_release)
- end
- release_deleted(old_release)
- end
- end
-
- def all_releases
- Dir.glob(Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to) + "/releases/*").sort
- end
-
- def update_cached_repo
- if new_resource.svn_force_export
- # TODO assertion, non-recoverable - @scm_provider must be svn if force_export?
- svn_force_export
- else
- run_scm_sync
- end
- end
-
- def run_scm_sync
- @scm_provider.run_action(:sync)
- end
-
- def svn_force_export
- Chef::Log.info "#{new_resource} exporting source repository"
- @scm_provider.run_action(:force_export)
- end
-
- def copy_cached_repo
- target_dir_path = new_resource.deploy_to + "/releases"
- converge_by("deploy from repo to #{target_dir_path} ") do
- FileUtils.rm_rf(release_path) if ::File.exist?(release_path)
- FileUtils.mkdir_p(target_dir_path)
- FileUtils.cp_r(::File.join(new_resource.destination, "."), release_path, :preserve => true)
- Chef::Log.info "#{new_resource} copied the cached checkout to #{release_path}"
- end
- end
-
- def enforce_ownership
- converge_by("force ownership of #{new_resource.deploy_to} to #{new_resource.group}:#{new_resource.user}") do
- FileUtils.chown_R(new_resource.user, new_resource.group, new_resource.deploy_to, :force => true)
- Chef::Log.info("#{new_resource} set user to #{new_resource.user}") if new_resource.user
- Chef::Log.info("#{new_resource} set group to #{new_resource.group}") if new_resource.group
- end
- end
-
- def verify_directories_exist
- create_dir_unless_exists(new_resource.deploy_to)
- create_dir_unless_exists(new_resource.shared_path)
- end
-
- def link_current_release_to_production
- converge_by(["remove existing link at #{new_resource.current_path}",
- "link release #{release_path} into production at #{new_resource.current_path}"]) do
- FileUtils.rm_f(new_resource.current_path)
- begin
- FileUtils.ln_sf(release_path, new_resource.current_path)
- rescue => e
- raise Chef::Exceptions::FileNotFound.new("Cannot symlink current release to production: #{e.message}")
- end
- Chef::Log.info "#{new_resource} linked release #{release_path} into production at #{new_resource.current_path}"
- end
- enforce_ownership
- end
-
- def run_symlinks_before_migrate
- links_info = new_resource.symlink_before_migrate.map { |src, dst| "#{src} => #{dst}" }.join(", ")
- converge_by("make pre-migration symlinks: #{links_info}") do
- new_resource.symlink_before_migrate.each do |src, dest|
- begin
- FileUtils.ln_sf(new_resource.shared_path + "/#{src}", release_path + "/#{dest}")
- rescue => e
- raise Chef::Exceptions::FileNotFound.new("Cannot symlink #{new_resource.shared_path}/#{src} to #{release_path}/#{dest} before migrate: #{e.message}")
- end
- end
- Chef::Log.info "#{new_resource} made pre-migration symlinks"
- end
- end
-
- def link_tempfiles_to_current_release
- dirs_info = new_resource.create_dirs_before_symlink.join(",")
- new_resource.create_dirs_before_symlink.each do |dir|
- create_dir_unless_exists(release_path + "/#{dir}")
- end
- Chef::Log.info("#{new_resource} created directories before symlinking: #{dirs_info}")
-
- links_info = new_resource.symlinks.map { |src, dst| "#{src} => #{dst}" }.join(", ")
- converge_by("link shared paths into current release: #{links_info}") do
- new_resource.symlinks.each do |src, dest|
- begin
- FileUtils.ln_sf(::File.join(new_resource.shared_path, src), ::File.join(release_path, dest))
- rescue => e
- raise Chef::Exceptions::FileNotFound.new("Cannot symlink shared data #{::File.join(new_resource.shared_path, src)} to #{::File.join(release_path, dest)}: #{e.message}")
- end
- end
- Chef::Log.info("#{new_resource} linked shared paths into current release: #{links_info}")
- end
- run_symlinks_before_migrate
- enforce_ownership
- end
-
- def create_dirs_before_symlink
- end
-
- def purge_tempfiles_from_current_release
- log_info = new_resource.purge_before_symlink.join(", ")
- converge_by("purge directories in checkout #{log_info}") do
- new_resource.purge_before_symlink.each { |dir| FileUtils.rm_rf(release_path + "/#{dir}") }
- Chef::Log.info("#{new_resource} purged directories in checkout #{log_info}")
- end
- end
-
- protected
-
- # Internal callback, called after copy_cached_repo.
- # Override if you need to keep state externally.
- # Note that YOU are responsible for implementing whyrun-friendly behavior
- # in any actions you take in this callback.
- def release_created(release_path)
- end
-
- # Note that YOU are responsible for using appropriate whyrun nomenclature
- # Override if you need to keep state externally.
- # Note that YOU are responsible for implementing whyrun-friendly behavior
- # in any actions you take in this callback.
- def release_deleted(release_path)
- end
-
- def release_slug
- raise Chef::Exceptions::Override, "You must override release_slug in #{self}"
- end
-
- def install_gems
- gem_resource_collection_runner.converge
- end
-
- def gem_resource_collection_runner
- child_context = run_context.create_child
- gem_packages.each { |rbgem| child_context.resource_collection.insert(rbgem) }
- Chef::Runner.new(child_context)
- end
-
- def gem_packages
- return [] unless ::File.exist?("#{release_path}/gems.yml")
- gems = YAML.load(IO.read("#{release_path}/gems.yml"))
-
- gems.map do |g|
- r = Chef::Resource::GemPackage.new(g[:name], run_context)
- r.version g[:version]
- r.action :install
- r.source "http://gems.github.com"
- r
- end
- end
-
- def run_options(run_opts = {})
- run_opts[:user] = new_resource.user if new_resource.user
- run_opts[:group] = new_resource.group if new_resource.group
- run_opts[:environment] = new_resource.environment if new_resource.environment
- run_opts[:log_tag] = new_resource.to_s
- run_opts[:log_level] ||= :debug
- if run_opts[:log_level] == :info
- if STDOUT.tty? && !Chef::Config[:daemon] && Chef::Log.info?
- run_opts[:live_stream] = STDOUT
- end
- end
- run_opts
- end
-
- def run_callback_from_file(callback_file)
- Chef::Log.info "#{new_resource} queueing checkdeploy hook #{callback_file}"
- recipe_eval do
- Dir.chdir(release_path) do
- from_file(callback_file) if ::File.exist?(callback_file)
- end
- end
- end
-
- def create_dir_unless_exists(dir)
- if ::File.directory?(dir)
- Chef::Log.debug "#{new_resource} not creating #{dir} because it already exists"
- return false
- end
- converge_by("create new directory #{dir}") do
- begin
- FileUtils.mkdir_p(dir)
- Chef::Log.debug "#{new_resource} created directory #{dir}"
- if new_resource.user
- FileUtils.chown(new_resource.user, nil, dir)
- Chef::Log.debug("#{new_resource} set user to #{new_resource.user} for #{dir}")
- end
- if new_resource.group
- FileUtils.chown(nil, new_resource.group, dir)
- Chef::Log.debug("#{new_resource} set group to #{new_resource.group} for #{dir}")
- end
- rescue => e
- raise Chef::Exceptions::FileNotFound.new("Cannot create directory #{dir}: #{e.message}")
- end
- end
- end
-
- def with_rollback_on_error
- yield
- rescue ::Exception => e
- if new_resource.rollback_on_error
- Chef::Log.warn "Error on deploying #{release_path}: #{e.message}"
- failed_release = release_path
-
- if previous_release_path
- @release_path = previous_release_path
- rollback
- end
- converge_by("remove failed deploy #{failed_release}") do
- Chef::Log.info "Removing failed deploy #{failed_release}"
- FileUtils.rm_rf failed_release
- end
- release_deleted(failed_release)
- end
-
- raise
- end
-
- def save_release_state
- if ::File.exists?(new_resource.current_path)
- release = ::File.readlink(new_resource.current_path)
- @previous_release_path = release if ::File.exists?(release)
- end
- end
-
- def deployed?(release)
- all_releases.include?(release)
- end
-
- def current_release?(release)
- @previous_release_path == release
- end
- end
- end
-end
diff --git a/lib/chef/provider/deploy/revision.rb b/lib/chef/provider/deploy/revision.rb
deleted file mode 100644
index 06138e4f05..0000000000
--- a/lib/chef/provider/deploy/revision.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Author:: Tim Hinderliter (<tim@chef.io>)
-# Author:: Seth Falcon (<seth@chef.io>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/provider"
-require "chef/provider/deploy"
-require "chef/json_compat"
-
-class Chef
- class Provider
- class Deploy
- class Revision < Chef::Provider::Deploy
- provides :deploy_revision
- provides :deploy_branch
-
- def all_releases
- sorted_releases
- end
-
- def action_deploy
- validate_release_history!
- super
- end
-
- def cleanup!
- super
-
- known_releases = sorted_releases
-
- Dir["#{Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to)}/releases/*"].each do |release_dir|
- unless known_releases.include?(release_dir)
- converge_by("Remove unknown release in #{release_dir}") do
- FileUtils.rm_rf(release_dir)
- end
- end
- end
- end
-
- protected
-
- def release_created(release)
- sorted_releases { |r| r.delete(release); r << release }
- end
-
- def release_deleted(release)
- sorted_releases { |r| r.delete(release) }
- end
-
- def release_slug
- scm_provider.revision_slug
- end
-
- private
-
- def sorted_releases
- cache = load_cache
- if block_given?
- yield cache
- save_cache(cache)
- end
- cache
- end
-
- def validate_release_history!
- sorted_releases do |release_list|
- release_list.each do |path|
- release_list.delete(path) unless ::File.exist?(path)
- end
- end
- end
-
- def sorted_releases_from_filesystem
- Dir.glob(Chef::Util::PathHelper.escape_glob_dir(new_resource.deploy_to) + "/releases/*").sort_by { |d| ::File.ctime(d) }
- end
-
- def load_cache
- Chef::JSONCompat.parse(Chef::FileCache.load("revision-deploys/#{new_resource.name}"))
- rescue Chef::Exceptions::FileNotFound
- sorted_releases_from_filesystem
- end
-
- def save_cache(cache)
- Chef::FileCache.store("revision-deploys/#{new_resource.name}", Chef::JSONCompat.to_json(cache))
- cache
- end
-
- end
- end
- end
-end
diff --git a/lib/chef/provider/deploy/timestamped.rb b/lib/chef/provider/deploy/timestamped.rb
deleted file mode 100644
index 5486b092d3..0000000000
--- a/lib/chef/provider/deploy/timestamped.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# 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 Deploy
- class Timestamped < Chef::Provider::Deploy
- provides :timestamped_deploy
- provides :deploy
-
- protected
-
- def release_slug
- Time.now.utc.strftime("%Y%m%d%H%M%S")
- end
- end
- end
- end
-end
diff --git a/lib/chef/provider/dsc_script.rb b/lib/chef/provider/dsc_script.rb
index 654f202ed9..db7a5442ed 100644
--- a/lib/chef/provider/dsc_script.rb
+++ b/lib/chef/provider/dsc_script.rb
@@ -161,7 +161,11 @@ class Chef
if resource.changes_state?
# We ignore the last log message because it only contains the time it took, which looks weird
cleaned_messages = resource.change_log[0..-2].map { |c| c.sub(/^#{Regexp.escape(resource.name)}/, "").strip }
- "converge DSC resource #{resource.name} by #{cleaned_messages.find_all { |c| c != '' }.join("\n")}"
+ unless cleaned_messages.empty?
+ "converge DSC resource #{resource.name} by #{cleaned_messages.find_all { |c| c != '' }.join("\n")}"
+ else
+ "converge DSC resource #{resource.name}"
+ end
else
# This is needed because a dsc script can have resources that are both converged and not
"converge DSC resource #{resource.name} by doing nothing because it is already converged"
diff --git a/lib/chef/provider/erl_call.rb b/lib/chef/provider/erl_call.rb
deleted file mode 100644
index b73341bb16..0000000000
--- a/lib/chef/provider/erl_call.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# Author:: Joe Williams (<joe@joetify.com>)
-# Copyright:: Copyright 2009-2016, Joe Williams
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/log"
-require "chef/provider"
-
-class Chef
- class Provider
- class ErlCall < Chef::Provider
-
- provides :erl_call
-
- def initialize(node, new_resource)
- super(node, new_resource)
- end
-
- def load_current_resource
- true
- end
-
- def action_run
- case new_resource.name_type
- when "sname"
- node = "-sname #{new_resource.node_name}"
- when "name"
- node = "-name #{new_resource.node_name}"
- end
-
- if new_resource.cookie
- cookie = "-c #{new_resource.cookie}"
- else
- cookie = ""
- end
-
- if new_resource.distributed
- distributed = "-s"
- else
- distributed = ""
- end
-
- command = "erl_call -e #{distributed} #{node} #{cookie}"
-
- converge_by("run erlang block") do
- so = shell_out!(command, input: new_resource.code)
-
- # fail if stderr contains anything
- if so.stderr.length > 0
- raise Chef::Exceptions::ErlCall, so.stderr
- end
-
- # fail if the first 4 characters aren't "{ok,"
- unless so.stdout[0..3].include?("{ok,")
- raise Chef::Exceptions::ErlCall, so.stdout
- end
-
- end
- end
-
- end
- end
-end
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index fea77dd7ea..86e7e5a5c4 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -339,7 +339,7 @@ class Chef
if tempfile
new_resource.verify.each do |v|
if ! v.verify(tempfile.path)
- raise Chef::Exceptions::ValidationFailed.new "Proposed content for #{new_resource.path} failed verification #{v}"
+ raise Chef::Exceptions::ValidationFailed.new "Proposed content for #{new_resource.path} failed verification #{new_resource.sensitive ? '[sensitive]' : v}"
end
end
end
diff --git a/lib/chef/provider/group/dscl.rb b/lib/chef/provider/group/dscl.rb
index 71e42b36ba..fe152eda33 100644
--- a/lib/chef/provider/group/dscl.rb
+++ b/lib/chef/provider/group/dscl.rb
@@ -88,8 +88,12 @@ class Chef
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") )
+ search_gids = safe_dscl("search", "/Groups", "PrimaryGroupID", gid.to_s)
+
+ # dscl -search should not return anything if the gid doesn't exist,
+ # but on the off-chance that it does, check whether the given gid is
+ # in the output.
+ !!(search_gids =~ /\b#{gid}\b/)
end
def set_gid
diff --git a/lib/chef/provider/ifconfig.rb b/lib/chef/provider/ifconfig.rb
index 16bbe8124b..c8da5e255f 100644
--- a/lib/chef/provider/ifconfig.rb
+++ b/lib/chef/provider/ifconfig.rb
@@ -23,20 +23,14 @@ require "chef/resource/file"
require "chef/exceptions"
require "erb"
-# Recipe example:
-#
-# int = {Hash with your network settings...}
-#
-# ifconfig int['ip'] do
-# ignore_failure true
-# device int['dev']
-# mask int['mask']
-# gateway int['gateway']
-# mtu int['mtu']
-# end
-
class Chef
class Provider
+ # use the ifconfig resource to manage interfaces on *nix systems
+ #
+ # @example set a static ip on eth1
+ # ifconfig '33.33.33.80' do
+ # device 'eth1'
+ # end
class Ifconfig < Chef::Provider
provides :ifconfig
@@ -57,30 +51,98 @@ class Chef
@ifconfig_success = true
@interfaces = {}
- @status = shell_out("ifconfig")
- @status.stdout.each_line do |line|
- if !line[0..9].strip.empty?
- @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+)/ ? 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:/
+ @ifconfig_version = nil
+
+ @net_tools_version = shell_out("ifconfig --version")
+ @net_tools_version.stderr.each_line do |line|
+ if line =~ /^net-tools (\d+.\d+)/
+ @ifconfig_version = line.match(/^net-tools (\d+.\d+)/)[1]
end
+ end
+
+ if @ifconfig_version.nil?
+ raise "net-tools not found - this is required for ifconfig"
+ elsif @ifconfig_version.to_f < 2.0
+ # Example output for 1.60 is as follows: (sanitized but format intact)
+ # eth0 Link encap:Ethernet HWaddr 00:00:00:00:00:00
+ # inet addr:192.168.1.1 Bcast:192.168.0.1 Mask:255.255.248.0
+ # inet6 addr: 0000::00:0000:0000:0000/64 Scope:Link
+ # UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
+ # RX packets:65158911 errors:0 dropped:0 overruns:0 frame:0
+ # TX packets:41723949 errors:0 dropped:0 overruns:0 carrier:0
+ # collisions:0 txqueuelen:1000
+ # RX bytes:42664658792 (39.7 GiB) TX bytes:52722603938 (49.1 GiB)
+ # Interrupt:30
+ @status = shell_out("ifconfig")
+ @status.stdout.each_line do |line|
+ if !line[0..9].strip.empty?
+ @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+)/ ? 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
- 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"])
+ 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
+ elsif @ifconfig_version.to_f >= 2.0
+ # Example output for 2.10-alpha is as follows: (sanitized but format intact)
+ # eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
+ # inet 192.168.1.1 netmask 255.255.240.0 broadcast 192.168.0.1
+ # inet6 0000::0000:000:0000:0000 prefixlen 64 scopeid 0x20<link>
+ # ether 00:00:00:00:00:00 txqueuelen 1000 (Ethernet)
+ # RX packets 2383836 bytes 1642630840 (1.5 GiB)
+ # RX errors 0 dropped 0 overruns 0 frame 0
+ # TX packets 1244218 bytes 977339327 (932.0 MiB)
+ # TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
+ @status = shell_out("ifconfig")
+ @status.stdout.each_line do |line|
+ addr_regex = /^(\w+):?(\d*):?\ .+$/
+ if line =~ addr_regex
+ if line.match(addr_regex).nil?
+ @int_name = "nil"
+ elsif line.match(addr_regex)[2] == ""
+ @int_name = line.match(addr_regex)[1]
+ @interfaces[@int_name] = Hash.new
+ @interfaces[@int_name]["mtu"] = (line =~ /mtu (\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /mtu/ && @interfaces[@int_name]["mtu"].nil?
+ else
+ @int_name = "#{line.match(addr_regex)[1]}:#{line.match(addr_regex)[2]}"
+ @interfaces[@int_name] = Hash.new
+ @interfaces[@int_name]["mtu"] = (line =~ /mtu (\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /mtu/ && @interfaces[@int_name]["mtu"].nil?
+ end
+ else
+ @interfaces[@int_name]["inet_addr"] = (line =~ /inet (\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /inet/ && @interfaces[@int_name]["inet_addr"].nil?
+ @interfaces[@int_name]["bcast"] = (line =~ /broadcast (\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /broadcast/ && @interfaces[@int_name]["bcast"].nil?
+ @interfaces[@int_name]["mask"] = (line =~ /netmask (\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /netmask/ && @interfaces[@int_name]["mask"].nil?
+ @interfaces[@int_name]["hwaddr"] = (line =~ /ether (\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /ether/ && @interfaces[@int_name]["hwaddr"].nil?
+ @interfaces[@int_name]["metric"] = (line =~ /Metric:(\S+)/ ? Regexp.last_match(1) : "nil") if line =~ /Metric:/ && @interfaces[@int_name]["metric"].nil?
+ 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
end
current_resource
end
diff --git a/lib/chef/provider/launchd.rb b/lib/chef/provider/launchd.rb
index 8281410d42..8d868784dd 100644
--- a/lib/chef/provider/launchd.rb
+++ b/lib/chef/provider/launchd.rb
@@ -17,7 +17,6 @@
#
require "chef/provider"
-require "chef/resource/launchd"
require "chef/resource/file"
require "chef/resource/cookbook_file"
require "chef/resource/macosx_service"
diff --git a/lib/chef/provider/log.rb b/lib/chef/provider/log.rb
index fbbc053b5b..214f284fbb 100644
--- a/lib/chef/provider/log.rb
+++ b/lib/chef/provider/log.rb
@@ -17,37 +17,27 @@
#
class Chef
-
class Provider
-
class Log
-
- # Chef log provider, allows logging to chef's logs from recipes
+ # Chef log provider, allows logging to chef's logs
class ChefLog < Chef::Provider
-
provides :log
# No concept of a 'current' resource for logs, this is a no-op
#
- # === Return
- # true:: Always return true
+ # @return [true] Always returns true
def load_current_resource
true
end
# Write the log to Chef's log
#
- # === Return
- # true:: Always return true
+ # @return [true] Always returns true
def action_write
Chef::Log.send(new_resource.level, new_resource.message)
new_resource.updated_by_last_action(true) if Chef::Config[:count_log_resource_updates]
end
-
end
-
end
-
end
-
end
diff --git a/lib/chef/provider/mount/mount.rb b/lib/chef/provider/mount/mount.rb
index c3b1cc0141..0be45e80da 100644
--- a/lib/chef/provider/mount/mount.rb
+++ b/lib/chef/provider/mount/mount.rb
@@ -146,6 +146,11 @@ class Chef
end
end
+ # Return appropriate default mount options according to the given os.
+ def default_mount_options
+ node[:os] == "linux" ? "defaults" : "rw"
+ end
+
def enable_fs
if @current_resource.enabled && mount_options_unchanged?
Chef::Log.debug("#{@new_resource} is already enabled - nothing to do")
@@ -158,7 +163,7 @@ class Chef
disable_fs
end
::File.open("/etc/fstab", "a") do |fstab|
- fstab.puts("#{device_fstab} #{@new_resource.mount_point} #{@new_resource.fstype} #{@new_resource.options.nil? ? "defaults" : @new_resource.options.join(",")} #{@new_resource.dump} #{@new_resource.pass}")
+ fstab.puts("#{device_fstab} #{@new_resource.mount_point} #{@new_resource.fstype} #{@new_resource.options.nil? ? default_mount_options : @new_resource.options.join(",")} #{@new_resource.dump} #{@new_resource.pass}")
Chef::Log.debug("#{@new_resource} is enabled at #{@new_resource.mount_point}")
end
end
diff --git a/lib/chef/provider/package.rb b/lib/chef/provider/package.rb
index 4810728524..df3f2a46b1 100644
--- a/lib/chef/provider/package.rb
+++ b/lib/chef/provider/package.rb
@@ -220,7 +220,7 @@ class Chef
end
def action_lock
- if package_locked(new_resource.name, new_resource.version) == false
+ unless package_locked(new_resource.package_name, new_resource.version)
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|
@@ -234,7 +234,7 @@ class Chef
end
def action_unlock
- if package_locked(new_resource.name, new_resource.version) == true
+ if package_locked(new_resource.package_name, new_resource.version)
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|
@@ -323,10 +323,38 @@ class Chef
#
# Note that most likely we need a spaceship operator on versions that subclasses can implement
# and we should have `version_compare(v1, v2)` that returns `v1 <=> v2`.
+
+ # This method performs a strict equality check between two strings representing version numbers
#
+ # This function will eventually be deprecated in favour of the below version_equals function.
+
def target_version_already_installed?(current_version, target_version)
- return false unless current_version && target_version
- current_version == target_version
+ version_equals?(current_version, target_version)
+ end
+
+ # Note that most likely we need a spaceship operator on versions that subclasses can implement
+ # and we should have `version_compare(v1, v2)` that returns `v1 <=> v2`.
+
+ # This method performs a strict equality check between two strings representing version numbers
+ #
+ def version_equals?(v1, v2)
+ return false unless v1 && v2
+ v1 == v2
+ end
+
+ # This function compares two version numbers and returns 'spaceship operator' style results, ie:
+ # if v1 < v2 then return -1
+ # if v1 = v2 then return 0
+ # if v1 > v2 then return 1
+ # if v1 and v2 are not comparable then return nil
+ #
+ # By default, this function will use Gem::Version comparison. Subclasses can reimplement this method
+ # for package-management system specific versions.
+ def version_compare(v1, v2)
+ gem_v1 = Gem::Version.new(v1)
+ gem_v2 = Gem::Version.new(v2)
+
+ gem_v1 <=> gem_v2
end
# Check the current_version against the new_resource.version, possibly using fuzzy
@@ -439,16 +467,22 @@ class Chef
each_package do |package_name, new_version, current_version, candidate_version|
case action
when :upgrade
- if target_version_already_installed?(current_version, new_version)
+ if version_equals?(current_version, new_version)
# this is an odd use case
Chef::Log.debug("#{new_resource} #{package_name} #{new_version} is already installed -- you are equality pinning with an :upgrade action, this may be deprecated in the future")
target_version_array.push(nil)
- elsif target_version_already_installed?(current_version, candidate_version)
+ elsif version_equals?(current_version, candidate_version)
Chef::Log.debug("#{new_resource} #{package_name} #{candidate_version} is already installed")
target_version_array.push(nil)
elsif candidate_version.nil?
Chef::Log.debug("#{new_resource} #{package_name} has no candidate_version to upgrade to")
target_version_array.push(nil)
+ elsif current_version.nil?
+ Chef::Log.debug("#{new_resource} has no existing installed version. Installing install #{candidate_version}")
+ target_version_array.push(candidate_version)
+ elsif version_compare(current_version, candidate_version) == 1 && !new_resource.allow_downgrade
+ Chef::Log.debug("#{new_resource} #{package_name} has installed version #{current_version}, which is newer than available version #{candidate_version}. Skipping...)")
+ target_version_array.push(nil)
else
Chef::Log.debug("#{new_resource} #{package_name} is out of date, will upgrade to #{candidate_version}")
target_version_array.push(candidate_version)
diff --git a/lib/chef/provider/package/apt.rb b/lib/chef/provider/package/apt.rb
index 3f8c34f50c..d307ba5003 100644
--- a/lib/chef/provider/package/apt.rb
+++ b/lib/chef/provider/package/apt.rb
@@ -71,22 +71,18 @@ class Chef
end
def package_locked(name, version)
- islocked = false
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
+ locked_packages = locked.stdout.each_line.map do |line|
+ line.strip
end
- islocked
+ name.all? { |n| locked_packages.include? n }
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, options, "install", package_name)
+ run_noninteractive("apt-get", "-q", "-y", config_file_options, default_release_options, options, "install", package_name)
end
def upgrade_package(name, version)
@@ -127,6 +123,22 @@ class Chef
private
+ # compare 2 versions to each other to see which is newer.
+ # this differs from the standard package method because we
+ # need to be able to parse debian version strings which contain
+ # tildes which Gem cannot properly parse
+ #
+ # @return [Integer] 1 if v1 > v2. 0 if they're equal. -1 if v1 < v2
+ def version_compare(v1, v2)
+ if !shell_out_compact_timeout("dpkg", "--compare-versions", v1.to_s, "gt", v2.to_s).error?
+ 1
+ elsif !shell_out_compact_timeout("dpkg", "--compare-versions", v1.to_s, "eq", v2.to_s).error?
+ 0
+ else
+ -1
+ end
+ end
+
# Runs command via shell_out with magic environment to disable
# interactive prompts. Command is run with default localization rather
# than forcing locale to "C", so command output may not be stable.
@@ -141,6 +153,20 @@ class Chef
end
end
+ def config_file_options
+ # If the user has specified config file options previously, respect those.
+ return if Array(options).any? { |opt| opt =~ /--force-conf/ }
+
+ # It doesn't make sense to install packages in a scenario that can
+ # result in a prompt. Have users decide up-front whether they want to
+ # forcibly overwrite the config file, otherwise preserve it.
+ if new_resource.overwrite_config_files
+ [ "-o", "Dpkg::Options::=--force-confnew" ]
+ else
+ [ "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold" ]
+ end
+ end
+
def resolve_package_versions(pkg)
current_version = nil
candidate_version = nil
diff --git a/lib/chef/provider/package/chocolatey.rb b/lib/chef/provider/package/chocolatey.rb
index a1ec4504a0..3536d807ad 100644
--- a/lib/chef/provider/package/chocolatey.rb
+++ b/lib/chef/provider/package/chocolatey.rb
@@ -141,6 +141,17 @@ EOS
private
+ def version_compare(v1, v2)
+ if v1 == "latest" || v2 == "latest"
+ return 0
+ end
+
+ gem_v1 = Gem::Version.new(v1)
+ gem_v2 = Gem::Version.new(v2)
+
+ gem_v1 <=> gem_v2
+ end
+
# Magic to find where chocolatey is installed in the system, and to
# return the full path of choco.exe
#
@@ -226,15 +237,20 @@ EOS
#
# @return [Hash] name-to-version mapping of available packages
def available_packages
- @available_packages ||=
- begin
- cmd = [ "list -r #{package_name_array.join ' '}" ]
- cmd.push( "-source #{new_resource.source}" ) if new_resource.source
- raw = parse_list_output(*cmd)
- raw.keys.each_with_object({}) do |name, available|
- available[name] = desired_name_versions[name] || raw[name]
+ return @available_packages if @available_packages
+ @available_packages = {}
+ package_name_array.each do |pkg|
+ available_versions =
+ begin
+ cmd = [ "list -r #{pkg}" ]
+ cmd.push( "-source #{new_resource.source}" ) if new_resource.source
+ raw = parse_list_output(*cmd)
+ raw.keys.each_with_object({}) do |name, available|
+ available[name] = desired_name_versions[name] || raw[name]
+ end
end
- end
+ @available_packages.merge! available_versions
+ end
@available_packages
end
diff --git a/lib/chef/provider/package/dnf.rb b/lib/chef/provider/package/dnf.rb
index 31279e8312..90a5596727 100644
--- a/lib/chef/provider/package/dnf.rb
+++ b/lib/chef/provider/package/dnf.rb
@@ -35,13 +35,18 @@ class Chef
use_multipackage_api
use_package_name_for_source
- provides :package, platform_family: %w{fedora amazon} do
- which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
- end
+ # all rhel variants >= 8 will use DNF
+ provides :package, platform_family: "rhel", platform_version: ">= 8"
+
+ # fedora >= 22 uses DNF
+ provides :package, platform: "fedora", platform_version: ">= 22"
- provides :package, platform_family: %w{rhel}, platform_version: ">= 8"
+ # amazon will eventually use DNF
+ provides :package, platform: "amazon" do
+ which("dnf")
+ end
- provides :dnf_package, os: "linux"
+ provides :dnf_package
#
# Most of the magic in this class happens in the python helper script. The ruby side of this
@@ -126,6 +131,10 @@ class Chef
end
end
+ def version_compare(v1, v2)
+ python_helper.compare_versions(v1, v2)
+ end
+
# @returns Array<Version>
def available_version(index)
@available_version ||= []
@@ -139,7 +148,7 @@ class Chef
@available_version[index]
end
- # @returns Array<Version>
+ # @return [Array<Version>]
def installed_version(index)
@installed_version ||= []
@installed_version[index] ||= if new_resource.source
diff --git a/lib/chef/provider/package/dnf/dnf_helper.py b/lib/chef/provider/package/dnf/dnf_helper.py
index eb4d238f65..501d6fceee 100644
--- a/lib/chef/provider/package/dnf/dnf_helper.py
+++ b/lib/chef/provider/package/dnf/dnf_helper.py
@@ -26,6 +26,14 @@ def flushcache():
pass
get_sack().load_system_repo(build_cache=True)
+def versioncompare(versions):
+ sack = get_sack()
+ if (versions[0] is None) or (versions[1] is None):
+ sys.stdout.write('0\n')
+ else:
+ evr_comparison = sack.evr_cmp(versions[0], versions[1])
+ sys.stdout.write('{}\n'.format(evr_comparison))
+
def query(command):
sack = get_sack()
@@ -86,5 +94,7 @@ while 1:
query(command)
elif command['action'] == "flushcache":
flushcache()
+ elif command['action'] == "versioncompare":
+ versioncompare(command['versions'])
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
index 04f0298861..1801caa1c1 100644
--- a/lib/chef/provider/package/dnf/python_helper.rb
+++ b/lib/chef/provider/package/dnf/python_helper.rb
@@ -61,6 +61,15 @@ class Chef
start if stdin.nil?
end
+ def compare_versions(version1, version2)
+ with_helper do
+ json = build_version_query("versioncompare", [version1, version2])
+ Chef::Log.debug "sending '#{json}' to python helper"
+ stdin.syswrite json + "\n"
+ stdout.sysread(4096).chomp.to_i
+ end
+ end
+
# @returns Array<Version>
def query(action, provides, version = nil, arch = nil)
with_helper do
@@ -109,6 +118,12 @@ class Chef
FFI_Yajl::Encoder.encode(hash)
end
+ def build_version_query(action, versions)
+ hash = { "action" => action }
+ hash["versions"] = versions
+ 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
diff --git a/lib/chef/provider/package/dpkg.rb b/lib/chef/provider/package/dpkg.rb
index 89a57affac..cf92e6d3e7 100644
--- a/lib/chef/provider/package/dpkg.rb
+++ b/lib/chef/provider/package/dpkg.rb
@@ -106,6 +106,22 @@ class Chef
private
+ # compare 2 versions to each other to see which is newer.
+ # this differs from the standard package method because we
+ # need to be able to parse debian version strings which contain
+ # tildes which Gem cannot properly parse
+ #
+ # @return [Integer] 1 if v1 > v2. 0 if they're equal. -1 if v1 < v2
+ def version_compare(v1, v2)
+ if !shell_out_compact_timeout("dpkg", "--compare-versions", v1.to_s, "gt", v2.to_s).error?
+ 1
+ elsif !shell_out_compact_timeout("dpkg", "--compare-versions", v1.to_s, "eq", v2.to_s).error?
+ 0
+ else
+ -1
+ end
+ end
+
def read_current_version_of_package(package_name)
Chef::Log.debug("#{new_resource} checking install state of #{package_name}")
status = shell_out_compact_timeout!("dpkg", "-s", package_name, returns: [0, 1])
diff --git a/lib/chef/provider/package/powershell.rb b/lib/chef/provider/package/powershell.rb
index 3912dd23af..9111869c2b 100644
--- a/lib/chef/provider/package/powershell.rb
+++ b/lib/chef/provider/package/powershell.rb
@@ -61,11 +61,11 @@ class Chef
def remove_package(names, versions)
names.each_with_index do |name, index|
if versions && !versions[index].nil?
- powershell_out( "Uninstall-Package '#{name}' -Force -ForceBootstrap -RequiredVersion #{versions[index]}", timeout: new_resource.timeout)
+ powershell_out("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
+ version = powershell_out("(Uninstall-Package '#{name}' -Force -ForceBootstrap).Version", timeout: new_resource.timeout).stdout.strip
unless version.empty?
Chef::Log.info("Removed package '#{name}' with version #{version}")
end
@@ -79,9 +79,9 @@ class Chef
versions = []
new_resource.package_name.each_with_index do |name, index|
version = if new_resource.version && !new_resource.version[index].nil?
- powershell_out("(Find-Package '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ powershell_out("(Find-Package '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force).Version", 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
+ powershell_out("(Find-Package '#{name}' -ForceBootstrap -Force).Version", timeout: new_resource.timeout).stdout.strip
end
if version.empty?
version = nil
@@ -96,9 +96,9 @@ class Chef
version_list = []
new_resource.package_name.each_with_index do |name, index|
version = if new_resource.version && !new_resource.version[index].nil?
- powershell_out("(Get-Package -Name '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", timeout: new_resource.timeout).stdout.strip
+ powershell_out("(Get-Package -Name '#{name}' -RequiredVersion #{new_resource.version[index]} -ForceBootstrap -Force).Version", 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
+ powershell_out("(Get-Package -Name '#{name}' -ForceBootstrap -Force).Version", timeout: new_resource.timeout).stdout.strip
end
if version.empty?
version = nil
diff --git a/lib/chef/provider/package/rpm.rb b/lib/chef/provider/package/rpm.rb
index 7ec24f8c24..07617c814e 100644
--- a/lib/chef/provider/package/rpm.rb
+++ b/lib/chef/provider/package/rpm.rb
@@ -18,6 +18,7 @@
require "chef/provider/package"
require "chef/resource/package"
require "chef/mixin/get_source_from_package"
+require "chef/provider/package/yum/rpm_utils"
class Chef
class Provider
@@ -109,6 +110,10 @@ class Chef
private
+ def version_compare(v1, v2)
+ Chef::Provider::Package::Yum::RPMVersion.parse(v1) <=> Chef::Provider::Package::Yum::RPMVersion.parse(v2)
+ end
+
def uri_scheme?(str)
scheme = URI.split(str).first
return false unless scheme
diff --git a/lib/chef/provider/package/smartos.rb b/lib/chef/provider/package/smartos.rb
index 8e4368f7c1..66d23554df 100644
--- a/lib/chef/provider/package/smartos.rb
+++ b/lib/chef/provider/package/smartos.rb
@@ -3,7 +3,7 @@
# Bryan McLellan (btm@loftninjas.org)
# Matthew Landauer (matthew@openaustralia.org)
# Ben Rockwood (benr@joyent.com)
-# Copyright:: Copyright 2009-2016, Bryan McLellan, Matthew Landauer
+# Copyright:: Copyright 2009-2018, Bryan McLellan, Matthew Landauer
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -30,7 +30,7 @@ class Chef
attr_accessor :is_virtual_package
provides :package, platform: "smartos"
- provides :smartos_package, os: "solaris2", platform_family: "smartos"
+ provides :smartos_package, platform_family: "smartos"
def load_current_resource
Chef::Log.debug("#{new_resource} loading current resource")
diff --git a/lib/chef/provider/package/windows.rb b/lib/chef/provider/package/windows.rb
index ca9d1e813a..bade7f27a3 100644
--- a/lib/chef/provider/package/windows.rb
+++ b/lib/chef/provider/package/windows.rb
@@ -165,6 +165,10 @@ class Chef
#
# @return [Boolean] true if new_version is equal to or included in current_version
def target_version_already_installed?(current_version, new_version)
+ version_equals?(current_version, new_version)
+ end
+
+ def version_equals?(current_version, new_version)
Chef::Log.debug("Checking if #{new_resource} version '#{new_version}' is already installed. #{current_version} is currently installed")
if current_version.is_a?(Array)
current_version.include?(new_version)
@@ -179,6 +183,17 @@ class Chef
private
+ def version_compare(v1, v2)
+ if v1 == "latest" || v2 == "latest"
+ return 0
+ end
+
+ gem_v1 = Gem::Version.new(v1)
+ gem_v2 = Gem::Version.new(v2)
+
+ gem_v1 <=> gem_v2
+ end
+
def uninstall_registry_entries
@uninstall_registry_entries ||= Chef::Provider::Package::Windows::RegistryUninstallEntry.find_entries(new_resource.package_name)
end
diff --git a/lib/chef/provider/package/yum.rb b/lib/chef/provider/package/yum.rb
index d87e421409..4151b88242 100644
--- a/lib/chef/provider/package/yum.rb
+++ b/lib/chef/provider/package/yum.rb
@@ -100,15 +100,11 @@ class Chef
# @see Chef::Provider::Package#package_locked
def package_locked(name, version)
- islocked = false
locked = shell_out_with_timeout!("yum versionlock")
- locked.stdout.each_line do |line|
- line_package = line.sub(/-[^-]*-[^-]*$/, "").split(":").last.strip
- if line_package == name
- islocked = true
- end
+ locked_packages = locked.stdout.each_line.map do |line|
+ line.sub(/-[^-]*-[^-]*$/, "").split(":").last.strip
end
- islocked
+ name.all? { |n| locked_packages.include? n }
end
#
@@ -156,26 +152,6 @@ class Chef
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
-
private
#
@@ -190,6 +166,10 @@ class Chef
end
end
+ def version_compare(v1, v2)
+ RPMVersion.parse(v1) <=> RPMVersion.parse(v2)
+ end
+
# Enable or disable YumCache extra_repo_control
def manage_extra_repo_control
if new_resource.options
diff --git a/lib/chef/provider/package/zypper.rb b/lib/chef/provider/package/zypper.rb
index 41e8433046..05e6dbd8fc 100644
--- a/lib/chef/provider/package/zypper.rb
+++ b/lib/chef/provider/package/zypper.rb
@@ -76,15 +76,11 @@ class Chef
end
def package_locked(name, version)
- islocked = false
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
+ locked_packages = locked.stdout.each_line.map do |line|
+ line.split("|").shift(2).last.strip
end
- islocked
+ name.all? { |n| locked_packages.include? n }
end
def load_current_resource
@@ -103,7 +99,7 @@ class Chef
end
def install_package(name, version)
- zypper_package("install", *options, "--auto-agree-with-licenses", name, version)
+ zypper_package("install", *options, "--auto-agree-with-licenses", allow_downgrade, name, version)
end
def upgrade_package(name, version)
@@ -147,6 +143,10 @@ class Chef
def gpg_checks
"--no-gpg-checks" unless new_resource.gpg_check
end
+
+ def allow_downgrade
+ "--oldpackage" if new_resource.allow_downgrade
+ end
end
end
end
diff --git a/lib/chef/provider/reboot.rb b/lib/chef/provider/reboot.rb
index 32dc38f788..c09fbaa2c0 100644
--- a/lib/chef/provider/reboot.rb
+++ b/lib/chef/provider/reboot.rb
@@ -21,9 +21,19 @@ require "chef/provider"
class Chef
class Provider
+ # Use the reboot resource to reboot a node, a necessary step with some
+ # installations on certain platforms. This resource is supported for use on
+ # the Microsoft Windows, macOS, and Linux platforms.
+ #
+ # In using this resource via notifications, it's important to *only* use
+ # immediate notifications. Delayed notifications produce unintuitive and
+ # probably undesired results.
+ #
+ # @since 12.0.0
class Reboot < Chef::Provider
provides :reboot
+ # @return [void]
def load_current_resource
@current_resource ||= Chef::Resource::Reboot.new(new_resource.name)
current_resource.reason(new_resource.reason)
@@ -31,6 +41,8 @@ class Chef
current_resource
end
+ # add a reboot to the node run_context
+ # @return [void]
def request_reboot
node.run_context.request_reboot(
:delay_mins => new_resource.delay_mins,
diff --git a/lib/chef/provider/remote_directory.rb b/lib/chef/provider/remote_directory.rb
index 6f4956de96..94de68c557 100644
--- a/lib/chef/provider/remote_directory.rb
+++ b/lib/chef/provider/remote_directory.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -47,8 +47,6 @@ class Chef
!!@overwrite
end
- attr_accessor :managed_files
-
# Hash containing keys of the paths for all the files that we sync, plus all their
# parent directories.
#
@@ -153,7 +151,7 @@ class Chef
#
# FIXME: it should do breadth-first, see CHEF-5080 (please use a performant sort)
#
- # @return Array<String> The list of files to transfer
+ # @return [Array<String>] The list of files to transfer
# @api private
#
def files_to_transfer
diff --git a/lib/chef/provider/remote_file/http.rb b/lib/chef/provider/remote_file/http.rb
index ad044f9e3c..4732253e5b 100644
--- a/lib/chef/provider/remote_file/http.rb
+++ b/lib/chef/provider/remote_file/http.rb
@@ -61,12 +61,13 @@ class Chef
def fetch
http = Chef::HTTP::Simple.new(uri, http_client_opts)
+ tempfile = Chef::FileContentManagement::Tempfile.new(@new_resource).tempfile
if want_progress?
- tempfile = http.streaming_request_with_progress(uri, headers) do |size, total|
+ tempfile = http.streaming_request_with_progress(uri, headers, tempfile) do |size, total|
events.resource_update_progress(new_resource, size, total, progress_interval)
end
else
- tempfile = http.streaming_request(uri, headers)
+ tempfile = http.streaming_request(uri, headers, tempfile)
end
if tempfile
update_cache_control_data(tempfile, http.last_response)
diff --git a/lib/chef/provider/remote_file/network_file.rb b/lib/chef/provider/remote_file/network_file.rb
index a08bfd2453..f9dc7b0e7b 100644
--- a/lib/chef/provider/remote_file/network_file.rb
+++ b/lib/chef/provider/remote_file/network_file.rb
@@ -43,7 +43,7 @@ class Chef
tempfile = Chef::FileContentManagement::Tempfile.new(new_resource).tempfile
Chef::Log.debug("#{new_resource} staging #{@source} to #{tempfile.path}")
- with_user_context(new_resource.remote_user, new_resource.remote_password, new_resource.remote_domain) do
+ with_user_context(new_resource.remote_user, new_resource.remote_password, new_resource.remote_domain, new_resource.authentication) do
::File.open(@source, "rb") do |remote_file|
while data = remote_file.read(TRANSFER_CHUNK_SIZE)
tempfile.write(data)
diff --git a/lib/chef/provider/route.rb b/lib/chef/provider/route.rb
index 2439f45eda..2784ae43bc 100644
--- a/lib/chef/provider/route.rb
+++ b/lib/chef/provider/route.rb
@@ -181,12 +181,12 @@ class Chef
conf[dev] << config_file_contents(:delete)
end
end
- conf.each do |k, v|
+ conf.each_key do |k|
if new_resource.target == "default"
network_file_name = "/etc/sysconfig/network"
converge_by("write route default route to #{network_file_name}") do
Chef::Log.debug("#{new_resource} writing default route #{new_resource.gateway} to #{network_file_name}")
- if ::File.exists?(network_file_name)
+ if ::File.exist?(network_file_name)
network_file = ::Chef::Util::FileEdit.new(network_file_name)
network_file.search_file_replace_line /^GATEWAY=/, "GATEWAY=#{new_resource.gateway}"
network_file.insert_line_if_no_match /^GATEWAY=/, "GATEWAY=#{new_resource.gateway}"
diff --git a/lib/chef/provider/service/debian.rb b/lib/chef/provider/service/debian.rb
index 58a43d27f8..fcfa34ddf9 100644
--- a/lib/chef/provider/service/debian.rb
+++ b/lib/chef/provider/service/debian.rb
@@ -53,7 +53,7 @@ class Chef
requirements.assert(:all_actions) do |a|
a.assertion { @so_priority.exitstatus == 0 }
- a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -n -f #{current_resource.service_name} failed - #{@so_priority.inspect}"
+ a.failure_message Chef::Exceptions::Service, "/usr/sbin/update-rc.d -f #{current_resource.service_name} failed - #{@so_priority.inspect}"
# This can happen if the service is not yet installed,so we'll fake it.
a.whyrun ["Unable to determine priority of service, assuming service would have been correctly installed earlier in the run.",
"Assigning temporary priorities to continue.",
@@ -73,7 +73,7 @@ class Chef
def get_priority
priority = {}
- @so_priority = shell_out!("/usr/sbin/update-rc.d -n -f #{current_resource.service_name} remove")
+ @so_priority = shell_out!("/usr/sbin/update-rc.d -f #{current_resource.service_name} remove")
[@so_priority.stdout, @so_priority.stderr].each do |iop|
iop.each_line do |line|
diff --git a/lib/chef/provider/service/solaris.rb b/lib/chef/provider/service/solaris.rb
index 9c85fda05f..f2b1ec4262 100644
--- a/lib/chef/provider/service/solaris.rb
+++ b/lib/chef/provider/service/solaris.rb
@@ -31,7 +31,7 @@ class Chef
super
@init_command = "/usr/sbin/svcadm"
@status_command = "/bin/svcs"
- @maintenace = false
+ @maintenance = false
end
def load_current_resource
@@ -54,6 +54,8 @@ class Chef
end
def enable_service
+ # Running service status to update maintenance status to invoke svcadm clear
+ service_status
shell_out!(default_init_command, "clear", @new_resource.service_name) if @maintenance
enable_flags = [ "-s", @new_resource.options ].flatten.compact
shell_out!(default_init_command, "enable", *enable_flags, @new_resource.service_name)
@@ -93,6 +95,9 @@ class Chef
# dependency require_all/error svc:/milestone/multi-user:default (online)
# $
+ # Set the default value for maintenance
+ @maintenance = false
+
# load output into hash
status = {}
cmd.stdout.each_line do |line|
@@ -101,7 +106,6 @@ class Chef
end
# check service state
- @maintenance = false
case status["state"]
when "online"
@current_resource.enabled(true)
diff --git a/lib/chef/provider/service/systemd.rb b/lib/chef/provider/service/systemd.rb
index 2da35b3b9e..fa9d381267 100644
--- a/lib/chef/provider/service/systemd.rb
+++ b/lib/chef/provider/service/systemd.rb
@@ -77,7 +77,7 @@ class Chef::Provider::Service::Systemd < Chef::Provider::Service::Simple
def get_systemctl_options_args
if new_resource.user
- uid = node["etc"]["passwd"][new_resource.user]["uid"]
+ uid = Etc.getpwuid(new_resource.user).uid
options = {
:environment => {
"DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{uid}/bus",
diff --git a/lib/chef/provider/service/windows.rb b/lib/chef/provider/service/windows.rb
index 931e320695..d370ecff51 100644
--- a/lib/chef/provider/service/windows.rb
+++ b/lib/chef/provider/service/windows.rb
@@ -19,6 +19,7 @@
#
require "chef/provider/service/simple"
+require "chef/win32_service_constants"
if RUBY_PLATFORM =~ /mswin|mingw32|windows/
require "chef/win32/error"
require "win32/service"
@@ -30,6 +31,7 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
include Chef::Mixin::ShellOut
include Chef::ReservedNames::Win32::API::Error rescue LoadError
+ include Chef::Win32ServiceConstants
#Win32::Service.get_start_type
AUTO_START = "auto start"
@@ -50,18 +52,33 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
SERVICE_RIGHT = "SeServiceLogonRight"
def load_current_resource
- @current_resource = Chef::Resource::WindowsService.new(@new_resource.name)
- @current_resource.service_name(@new_resource.service_name)
- @current_resource.running(current_state == RUNNING)
- Chef::Log.debug "#{@new_resource} running: #{@current_resource.running}"
- case current_start_type
- when AUTO_START
- @current_resource.enabled(true)
- when DISABLED
- @current_resource.enabled(false)
+ @current_resource = Chef::Resource::WindowsService.new(new_resource.name)
+ current_resource.service_name(new_resource.service_name)
+
+ if Win32::Service.exists?(current_resource.service_name)
+ current_resource.running(current_state == RUNNING)
+ Chef::Log.debug "#{new_resource} running: #{current_resource.running}"
+ case current_startup_type
+ when :automatic
+ current_resource.enabled(true)
+ when :disabled
+ current_resource.enabled(false)
+ end
+ Chef::Log.debug "#{new_resource} enabled: #{current_resource.enabled}"
+
+ config_info = Win32::Service.config_info(current_resource.service_name)
+ current_resource.service_type(get_service_type(config_info.service_type)) if config_info.service_type
+ current_resource.startup_type(start_type_to_sym(config_info.start_type)) if config_info.start_type
+ current_resource.error_control(get_error_control(config_info.error_control)) if config_info.error_control
+ current_resource.binary_path_name(config_info.binary_path_name) if config_info.binary_path_name
+ current_resource.load_order_group(config_info.load_order_group) if config_info.load_order_group
+ current_resource.dependencies(config_info.dependencies) if config_info.dependencies
+ current_resource.run_as_user(config_info.service_start_name) if config_info.service_start_name
+ current_resource.display_name(config_info.display_name) if config_info.display_name
+ current_resource.delayed_start(current_delayed_start) if current_delayed_start
end
- Chef::Log.debug "#{@new_resource} enabled: #{@current_resource.enabled}"
- @current_resource
+
+ current_resource
end
def start_service
@@ -175,8 +192,52 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
end
end
+ action :create do
+ if Win32::Service.exists?(new_resource.service_name)
+ Chef::Log.debug "#{new_resource} already exists - nothing to do"
+ return
+ end
+
+ converge_by("create service #{new_resource.service_name}") do
+ Win32::Service.new(windows_service_config)
+ end
+
+ converge_delayed_start
+ end
+
+ action :delete do
+ unless Win32::Service.exists?(new_resource.service_name)
+ Chef::Log.debug "#{new_resource} does not exist - nothing to do"
+ return
+ end
+
+ converge_by("delete service #{new_resource.service_name}") do
+ Win32::Service.delete(new_resource.service_name)
+ end
+ end
+
+ action :configure do
+ unless Win32::Service.exists?(new_resource.service_name)
+ Chef::Log.warn "#{new_resource} does not exist. Maybe you need to prepend action :create"
+ return
+ end
+
+ # Until #6300 is solved this is required
+ if new_resource.run_as_user == new_resource.class.properties[:run_as_user].default
+ new_resource.run_as_user = new_resource.class.properties[:run_as_user].default
+ end
+
+ converge_if_changed :service_type, :startup_type, :error_control,
+ :binary_path_name, :load_order_group, :dependencies,
+ :run_as_user, :display_name, :description do
+ Win32::Service.configure(windows_service_config(:configure))
+ end
+
+ converge_delayed_start
+ end
+
def action_enable
- if current_start_type != AUTO_START
+ if current_startup_type != :automatic
converge_by("enable service #{@new_resource}") do
enable_service
Chef::Log.info("#{@new_resource} enabled")
@@ -189,7 +250,7 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
end
def action_disable
- if current_start_type != DISABLED
+ if current_startup_type != :disabled
converge_by("disable service #{@new_resource}") do
disable_service
Chef::Log.info("#{@new_resource} disabled")
@@ -202,31 +263,13 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
end
def action_configure_startup
- case @new_resource.startup_type
- when :automatic
- if current_start_type != AUTO_START
- converge_by("set service #{@new_resource} startup type to automatic") do
- set_startup_type(:automatic)
- end
- else
- Chef::Log.debug("#{@new_resource} startup_type already automatic - nothing to do")
- end
- when :manual
- if current_start_type != MANUAL
- converge_by("set service #{@new_resource} startup type to manual") do
- set_startup_type(:manual)
- end
- else
- Chef::Log.debug("#{@new_resource} startup_type already manual - nothing to do")
- end
- when :disabled
- if current_start_type != DISABLED
- converge_by("set service #{@new_resource} startup type to disabled") do
- set_startup_type(:disabled)
- end
- else
- Chef::Log.debug("#{@new_resource} startup_type already disabled - nothing to do")
+ startup_type = @new_resource.startup_type
+ if current_startup_type != startup_type
+ converge_by("set service #{@new_resource} startup type to #{startup_type}") do
+ set_startup_type(startup_type)
end
+ else
+ Chef::Log.debug("#{@new_resource} startup_type already #{startup_type} - nothing to do")
end
# Avoid changing enabled from true/false for now
@@ -235,6 +278,14 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
private
+ def current_delayed_start
+ if service = Win32::Service.services.find { |x| x.service_name == new_resource.service_name }
+ service.delayed_start == 0 ? false : true
+ else
+ nil
+ end
+ end
+
def grant_service_logon(username)
begin
Chef::ReservedNames::Win32::Security.add_account_right(canonicalize_username(username), SERVICE_RIGHT)
@@ -260,8 +311,9 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
Win32::Service.status(@new_resource.service_name).current_state
end
- def current_start_type
- Win32::Service.config_info(@new_resource.service_name).start_type
+ def current_startup_type
+ start_type = Win32::Service.config_info(@new_resource.service_name).start_type
+ start_type_to_sym(start_type)
end
# Helper method that waits for a status to change its state since state
@@ -289,21 +341,143 @@ class Chef::Provider::Service::Windows < Chef::Provider::Service
end
end
- # Takes Win32::Service start_types
- def set_startup_type(type)
- # Set-Service Startup Type => Win32::Service Constant
- allowed_types = { :automatic => Win32::Service::AUTO_START,
- :manual => Win32::Service::DEMAND_START,
- :disabled => Win32::Service::DISABLED }
- unless allowed_types.keys.include?(type)
+ # @param type [Symbol]
+ # @return [Integer]
+ # @raise [Chef::Exceptions::ConfigurationError] if the startup type is
+ # not supported.
+ # @see Chef::Resource::WindowsService::ALLOWED_START_TYPES
+ def startup_type_to_int(type)
+ Chef::Resource::WindowsService::ALLOWED_START_TYPES.fetch(type) do
raise Chef::Exceptions::ConfigurationError, "#{@new_resource.name}: Startup type '#{type}' is not supported"
end
+ end
+
+ # Takes Win32::Service start_types
+ def set_startup_type(type)
+ startup_type = startup_type_to_int(type)
Chef::Log.debug "#{@new_resource.name} setting start_type to #{type}"
Win32::Service.configure(
:service_name => @new_resource.service_name,
- :start_type => allowed_types[type]
+ :start_type => startup_type
)
@new_resource.updated_by_last_action(true)
end
+
+ def windows_service_config(action = :create)
+ config = {}
+
+ config[:service_name] = new_resource.service_name
+ config[:display_name] = new_resource.display_name if new_resource.display_name
+ config[:service_type] = new_resource.service_type if new_resource.service_type
+ config[:start_type] = startup_type_to_int(new_resource.startup_type) if new_resource.startup_type
+ config[:error_control] = new_resource.error_control if new_resource.error_control
+ config[:binary_path_name] = new_resource.binary_path_name if new_resource.binary_path_name
+ config[:load_order_group] = new_resource.load_order_group if new_resource.load_order_group
+ config[:dependencies] = new_resource.dependencies if new_resource.dependencies
+ config[:service_start_name] = new_resource.run_as_user unless new_resource.run_as_user.empty?
+ config[:password] = new_resource.run_as_password unless new_resource.run_as_user.empty? || new_resource.run_as_password.empty?
+ config[:description] = new_resource.description if new_resource.description
+
+ case action
+ when :create
+ config[:desired_access] = new_resource.desired_access if new_resource.desired_access
+ end
+
+ config
+ end
+
+ def converge_delayed_start
+ config = {}
+ config[:service_name] = new_resource.service_name
+ config[:delayed_start] = new_resource.delayed_start ? 1 : 0
+
+ # Until #6300 is solved this is required
+ if new_resource.delayed_start == new_resource.class.properties[:delayed_start].default
+ new_resource.delayed_start = new_resource.class.properties[:delayed_start].default
+ end
+
+ converge_if_changed :delayed_start do
+ Win32::Service.configure(config)
+ end
+ end
+
+ # @return [Symbol]
+ def start_type_to_sym(start_type)
+ case start_type
+ when "auto start"
+ :automatic
+ when "boot start"
+ raise("Unsupported start type, #{start_type}. Submit bug request to fix.")
+ when "demand start"
+ :manual
+ when "disabled"
+ :disabled
+ when "system start"
+ raise("Unsupported start type, #{start_type}. Submit bug request to fix.")
+ else
+ raise("Unsupported start type, #{start_type}. Submit bug request to fix.")
+ end
+ end
+
+ def get_service_type(service_type)
+ case service_type
+ when "file system driver"
+ SERVICE_FILE_SYSTEM_DRIVER
+ when "kernel driver"
+ SERVICE_KERNEL_DRIVER
+ when "own process"
+ SERVICE_WIN32_OWN_PROCESS
+ when "share process"
+ SERVICE_WIN32_SHARE_PROCESS
+ when "recognizer driver"
+ SERVICE_RECOGNIZER_DRIVER
+ when "driver"
+ SERVICE_DRIVER
+ when "win32"
+ SERVICE_WIN32
+ when "all"
+ SERVICE_TYPE_ALL
+ when "own process, interactive"
+ SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS
+ when "share process, interactive"
+ SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_SHARE_PROCESS
+ else
+ raise("Unsupported service type, #{service_type}. Submit bug request to fix.")
+ end
+ end
+
+ # @return [Integer]
+ def get_start_type(start_type)
+ case start_type
+ when "auto start"
+ SERVICE_AUTO_START
+ when "boot start"
+ SERVICE_BOOT_START
+ when "demand start"
+ SERVICE_DEMAND_START
+ when "disabled"
+ SERVICE_DISABLED
+ when "system start"
+ SERVICE_SYSTEM_START
+ else
+ raise("Unsupported start type, #{start_type}. Submit bug request to fix.")
+ end
+ end
+
+ def get_error_control(error_control)
+ case error_control
+ when "critical"
+ SERVICE_ERROR_CRITICAL
+ when "ignore"
+ SERVICE_ERROR_IGNORE
+ when "normal"
+ SERVICE_ERROR_NORMAL
+ when "severe"
+ SERVICE_ERROR_SEVERE
+ else
+ nil
+ end
+ end
+
end
diff --git a/lib/chef/provider/support/yum_repo.erb b/lib/chef/provider/support/yum_repo.erb
index 6f1325573d..f60d8688da 100644
--- a/lib/chef/provider/support/yum_repo.erb
+++ b/lib/chef/provider/support/yum_repo.erb
@@ -61,6 +61,9 @@ keepalive=1
<% if @config.metadata_expire %>
metadata_expire=<%= @config.metadata_expire %>
<% end %>
+<% if @config.metalink %>
+metalink=<%= @config.metalink %>
+<% end %>
<% if @config.mirrorlist %>
mirrorlist=<%= @config.mirrorlist %>
<% end %>
@@ -112,6 +115,9 @@ sslclientkey=<%= @config.sslclientkey %>
<% unless @config.sslverify.nil? %>
sslverify=<%= ( @config.sslverify ) ? 'true' : 'false' %>
<% end %>
+<% if @config.throttle %>
+throttle=<%= @config.throttle %>
+<% end %>
<% if @config.timeout %>
timeout=<%= @config.timeout %>
<% end %>
diff --git a/lib/chef/provider/systemd_unit.rb b/lib/chef/provider/systemd_unit.rb
index a2ef64044b..420438775c 100644
--- a/lib/chef/provider/systemd_unit.rb
+++ b/lib/chef/provider/systemd_unit.rb
@@ -1,6 +1,6 @@
#
# Author:: Nathan Williams (<nath.e.will@gmail.com>)
-# Copyright:: Copyright 2016, Nathan Williams
+# Copyright:: Copyright 2016-2018, Nathan Williams
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -35,6 +35,7 @@ class Chef
def load_current_resource
@current_resource = Chef::Resource::SystemdUnit.new(new_resource.name)
+ current_resource.unit_name(new_resource.unit_name)
current_resource.content(::File.read(unit_path)) if ::File.exist?(unit_path)
current_resource.user(new_resource.user)
current_resource.enabled(enabled?)
@@ -57,7 +58,7 @@ class Chef
def action_create
if current_resource.content != new_resource.to_ini
- converge_by("creating unit: #{new_resource.name}") do
+ converge_by("creating unit: #{new_resource.unit_name}") do
manage_unit_file(:create)
daemon_reload if new_resource.triggers_reload
end
@@ -66,126 +67,144 @@ class Chef
def action_delete
if ::File.exist?(unit_path)
- converge_by("deleting unit: #{new_resource.name}") do
+ converge_by("deleting unit: #{new_resource.unit_name}") do
manage_unit_file(:delete)
daemon_reload if new_resource.triggers_reload
end
end
end
+ def action_preset
+ converge_by("restoring enable/disable preset configuration for unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:preset, new_resource.unit_name)
+ end
+ end
+
+ def action_revert
+ converge_by("reverting to vendor version of unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:revert, new_resource.unit_name)
+ end
+ end
+
def action_enable
if current_resource.static
- Chef::Log.debug("#{new_resource.name} is a static unit, enabling is a NOP.")
+ Chef::Log.debug("#{new_resource.unit_name} is a static unit, enabling is a NOP.")
end
unless current_resource.enabled || current_resource.static
- converge_by("enabling unit: #{new_resource.name}") do
- systemctl_execute!(:enable, new_resource.name)
+ converge_by("enabling unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:enable, new_resource.unit_name)
end
end
end
def action_disable
if current_resource.static
- Chef::Log.debug("#{new_resource.name} is a static unit, disabling is a NOP.")
+ Chef::Log.debug("#{new_resource.unit_name} is a static unit, disabling is a NOP.")
end
if current_resource.enabled && !current_resource.static
- converge_by("disabling unit: #{new_resource.name}") do
- systemctl_execute!(:disable, new_resource.name)
+ converge_by("disabling unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:disable, new_resource.unit_name)
end
end
end
+ def action_reenable
+ converge_by("reenabling unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:reenable, new_resource.unit_name)
+ end
+ end
+
def action_mask
unless current_resource.masked
- converge_by("masking unit: #{new_resource.name}") do
- systemctl_execute!(:mask, new_resource.name)
+ converge_by("masking unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:mask, new_resource.unit_name)
end
end
end
def action_unmask
if current_resource.masked
- converge_by("unmasking unit: #{new_resource.name}") do
- systemctl_execute!(:unmask, new_resource.name)
+ converge_by("unmasking unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:unmask, new_resource.unit_name)
end
end
end
def action_start
unless current_resource.active
- converge_by("starting unit: #{new_resource.name}") do
- systemctl_execute!(:start, new_resource.name)
+ converge_by("starting unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:start, new_resource.unit_name)
end
end
end
def action_stop
if current_resource.active
- converge_by("stopping unit: #{new_resource.name}") do
- systemctl_execute!(:stop, new_resource.name)
+ converge_by("stopping unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:stop, new_resource.unit_name)
end
end
end
def action_restart
- converge_by("restarting unit: #{new_resource.name}") do
- systemctl_execute!(:restart, new_resource.name)
+ converge_by("restarting unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:restart, new_resource.unit_name)
end
end
def action_reload
if current_resource.active
- converge_by("reloading unit: #{new_resource.name}") do
- systemctl_execute!(:reload, new_resource.name)
+ converge_by("reloading unit: #{new_resource.unit_name}") do
+ systemctl_execute!(:reload, new_resource.unit_name)
end
else
- Chef::Log.debug("#{new_resource.name} is not active, skipping reload.")
+ Chef::Log.debug("#{new_resource.unit_name} is not active, skipping reload.")
end
end
def action_try_restart
- converge_by("try-restarting unit: #{new_resource.name}") do
- systemctl_execute!("try-restart", new_resource.name)
+ converge_by("try-restarting unit: #{new_resource.unit_name}") do
+ systemctl_execute!("try-restart", new_resource.unit_name)
end
end
def action_reload_or_restart
- converge_by("reload-or-restarting unit: #{new_resource.name}") do
- systemctl_execute!("reload-or-restart", new_resource.name)
+ converge_by("reload-or-restarting unit: #{new_resource.unit_name}") do
+ systemctl_execute!("reload-or-restart", new_resource.unit_name)
end
end
def action_reload_or_try_restart
- converge_by("reload-or-try-restarting unit: #{new_resource.name}") do
- systemctl_execute!("reload-or-try-restart", new_resource.name)
+ converge_by("reload-or-try-restarting unit: #{new_resource.unit_name}") do
+ systemctl_execute!("reload-or-try-restart", new_resource.unit_name)
end
end
def active?
- systemctl_execute("is-active", new_resource.name).exitstatus == 0
+ systemctl_execute("is-active", new_resource.unit_name).exitstatus == 0
end
def enabled?
- systemctl_execute("is-enabled", new_resource.name).exitstatus == 0
+ systemctl_execute("is-enabled", new_resource.unit_name).exitstatus == 0
end
def masked?
- systemctl_execute(:status, new_resource.name).stdout.include?("masked")
+ systemctl_execute(:status, new_resource.unit_name).stdout.include?("masked")
end
def static?
- systemctl_execute("is-enabled", new_resource.name).stdout.include?("static")
+ systemctl_execute("is-enabled", new_resource.unit_name).stdout.include?("static")
end
private
def unit_path
if new_resource.user
- "/etc/systemd/user/#{new_resource.name}"
+ "/etc/systemd/user/#{new_resource.unit_name}"
else
- "/etc/systemd/system/#{new_resource.name}"
+ "/etc/systemd/system/#{new_resource.unit_name}"
end
end
@@ -226,10 +245,11 @@ class Chef
def systemctl_opts
@systemctl_opts ||=
if new_resource.user
+ uid = Etc.getpwuid(new_resource.user).uid
{
:user => new_resource.user,
:environment => {
- "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{node['etc']['passwd'][new_resource.user]['uid']}/bus",
+ "DBUS_SESSION_BUS_ADDRESS" => "unix:path=/run/user/#{uid}/bus",
},
}
else
diff --git a/lib/chef/provider/user/dscl.rb b/lib/chef/provider/user/dscl.rb
index 60167856d1..bc865b17c5 100644
--- a/lib/chef/provider/user/dscl.rb
+++ b/lib/chef/provider/user/dscl.rb
@@ -318,7 +318,7 @@ user password using shadow hash.")
end
def current_home_exists?
- ::File.exist?(current_resource.home)
+ !!current_resource.home && ::File.exist?(current_resource.home)
end
def new_home_exists?
diff --git a/lib/chef/provider/windows_path.rb b/lib/chef/provider/windows_path.rb
index b31789b4b9..1c78e20606 100644
--- a/lib/chef/provider/windows_path.rb
+++ b/lib/chef/provider/windows_path.rb
@@ -23,9 +23,10 @@ require "chef/exceptions"
class Chef
class Provider
class WindowsPath < Chef::Provider
-
include Chef::Mixin::WindowsEnvHelper if Chef::Platform.windows?
+ provides :windows_path
+
def load_current_resource
@current_resource = Chef::Resource::WindowsPath.new(new_resource.name)
@current_resource.path(new_resource.path)
@@ -37,12 +38,10 @@ class Chef
# the PATH environment variable. Ruby expects these to be expanded.
#
path = expand_path(new_resource.path)
- converge_by "Adding #{new_resource.path} to path environment variable" do
- declare_resource(:env, "path") do
- action :modify
- delim ::File::PATH_SEPARATOR
- value path.tr("/", '\\')
- end
+ declare_resource(:env, "path") do
+ action :modify
+ delim ::File::PATH_SEPARATOR
+ value path.tr("/", '\\')
end
end
diff --git a/lib/chef/provider/windows_task.rb b/lib/chef/provider/windows_task.rb
index 8703c30da9..d8754e7d5d 100644
--- a/lib/chef/provider/windows_task.rb
+++ b/lib/chef/provider/windows_task.rb
@@ -1,6 +1,6 @@
#
# Author:: Nimisha Sharad (<nimisha.sharad@msystechnologies.com>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -75,25 +75,39 @@ class Chef
def action_create
if current_resource.exists
+ Chef::Log.debug "#{new_resource} task exists"
if !(task_need_update? || new_resource.force)
- Chef::Log.info "#{new_resource} task already exists - nothing to do"
+ Chef::Log.info "#{new_resource} task does not need updating and force is not specified - nothing to do"
return
end
- # To merge current resource and new resource attributes
+ # Setting the attributes of new_resource as current_resource.
+ # This is required to handle update scenarios when the user specifies
+ # only those attributes in the recipe which require update
resource_attributes.each do |attribute|
new_resource_attribute = new_resource.send(attribute)
current_resource_attribute = current_resource.send(attribute)
+ # We accept start_day in mm/dd/yyyy format only. Hence while copying the start_day from system to new_resource.start_day,
+ # we are converting from system date format to mm/dd/yyyy
+ current_resource_attribute = convert_system_date_to_mm_dd_yyyy(current_resource_attribute) if attribute == "start_day" && current_resource_attribute != "N/A"
+ # Convert start_time into 24hr time format
+ current_resource_attribute = DateTime.parse(current_resource_attribute).strftime("%H:%M") if attribute == "start_time" && current_resource_attribute != "N/A"
new_resource.send("#{attribute}=", current_resource_attribute ) if current_resource_attribute && new_resource_attribute.nil?
end
end
basic_validation
options = {}
options["F"] = "" if new_resource.force || task_need_update?
- options["SC"] = schedule
+ if schedule == :none
+ options["SC"] = :once
+ options["ST"] = "00:00"
+ options["SD"] = convert_user_date_to_system_date "12/12/2012"
+ else
+ options["SC"] = schedule
+ options["ST"] = new_resource.start_time unless new_resource.start_time.nil? || new_resource.start_time == "N/A"
+ options["SD"] = convert_user_date_to_system_date new_resource.start_day unless new_resource.start_day.nil? || new_resource.start_day == "N/A"
+ end
options["MO"] = new_resource.frequency_modifier if frequency_modifier_allowed
options["I"] = new_resource.idle_time unless new_resource.idle_time.nil?
- options["SD"] = convert_user_date_to_system_date new_resource.start_day unless new_resource.start_day.nil?
- options["ST"] = new_resource.start_time unless new_resource.start_time.nil?
options["TR"] = new_resource.command
options["RU"] = new_resource.user
options["RP"] = new_resource.password if use_password?
@@ -106,77 +120,82 @@ class Chef
xml_options << "cwd" if new_resource.cwd
xml_options << "random_delay" if new_resource.random_delay
xml_options << "execution_time_limit" if new_resource.execution_time_limit
- update_task_xml(xml_options) unless xml_options.empty?
- new_resource.updated_by_last_action true
- Chef::Log.info "#{new_resource} task created"
+ converge_by("#{new_resource} task created") do
+ update_task_xml(xml_options) unless xml_options.empty?
+ end
end
def action_run
if current_resource.exists
+ Chef::Log.debug "#{new_resource} task exists"
if current_resource.status == :running
Chef::Log.info "#{new_resource} task is currently running, skipping run"
else
- run_schtasks "RUN"
- new_resource.updated_by_last_action true
- Chef::Log.info "#{new_resource} task ran"
+ converge_by("run scheduled task #{new_resource}") do
+ run_schtasks "RUN"
+ end
end
else
- Chef::Log.warn "#{new_resource} task doesn't exists - nothing to do"
+ Chef::Log.warn "#{new_resource} task does not exist - nothing to do"
end
end
def action_delete
if current_resource.exists
- # always need to force deletion
- run_schtasks "DELETE", "F" => ""
- new_resource.updated_by_last_action true
- Chef::Log.info "#{new_resource} task deleted"
+ Chef::Log.debug "#{new_resource} task exists"
+ converge_by("delete scheduled task #{new_resource}") do
+ # always need to force deletion
+ run_schtasks "DELETE", "F" => ""
+ end
else
- Chef::Log.warn "#{new_resource} task doesn't exists - nothing to do"
+ Chef::Log.warn "#{new_resource} task does not exist - nothing to do"
end
end
def action_end
if current_resource.exists
+ Chef::Log.debug "#{new_resource} task exists"
if current_resource.status != :running
Chef::Log.debug "#{new_resource} is not running - nothing to do"
else
- run_schtasks "END"
- new_resource.updated_by_last_action true
- Chef::Log.info "#{new_resource} task ended"
+ converge_by("#{new_resource} task ended") do
+ run_schtasks "END"
+ end
end
else
- Chef::Log.warn "#{new_resource} task doesn't exist - nothing to do"
+ Chef::Log.warn "#{new_resource} task does not exist - nothing to do"
end
end
def action_enable
if current_resource.exists
+ Chef::Log.debug "#{new_resource} task exists"
if current_resource.enabled
Chef::Log.debug "#{new_resource} already enabled - nothing to do"
else
- run_schtasks "CHANGE", "ENABLE" => ""
- new_resource.updated_by_last_action true
- Chef::Log.info "#{new_resource} task enabled"
+ converge_by("#{new_resource} task enabled") do
+ run_schtasks "CHANGE", "ENABLE" => ""
+ end
end
else
- Chef::Log.fatal "#{new_resource} task doesn't exist - nothing to do"
+ Chef::Log.fatal "#{new_resource} task does not exist - nothing to do"
raise Errno::ENOENT, "#{new_resource}: task does not exist, cannot enable"
end
end
def action_disable
if current_resource.exists
+ Chef::Log.info "#{new_resource} task exists"
if current_resource.enabled
- run_schtasks "CHANGE", "DISABLE" => ""
- new_resource.updated_by_last_action true
- Chef::Log.info "#{new_resource} task disabled"
+ converge_by("#{new_resource} task disabled") do
+ run_schtasks "CHANGE", "DISABLE" => ""
+ end
else
Chef::Log.warn "#{new_resource} already disabled - nothing to do"
end
else
- Chef::Log.warn "#{new_resource} task doesn't exist - nothing to do"
+ Chef::Log.warn "#{new_resource} task does not exist - nothing to do"
end
end
@@ -185,9 +204,15 @@ class Chef
# rubocop:disable Style/StringLiteralsInInterpolation
def run_schtasks(task_action, options = {})
cmd = "schtasks /#{task_action} /TN \"#{new_resource.task_name}\" "
- options.keys.each do |option|
- cmd += "/#{option} "
- cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == ""
+ options.each_key do |option|
+ unless option == "TR"
+ cmd += "/#{option} "
+ cmd += "\"#{options[option].to_s.gsub('"', "\\\"")}\" " unless options[option] == ""
+ end
+ end
+ # Appending Task Run [TR] option at the end since appending causing sometimes to append other options in option["TR"] value
+ if options["TR"]
+ cmd += "/TR \"#{options["TR"]} \" " unless task_action == "DELETE"
end
Chef::Log.debug("running: ")
Chef::Log.debug(" #{cmd}")
@@ -204,10 +229,9 @@ class Chef
current_resource.frequency_modifier != new_resource.frequency_modifier ||
current_resource.frequency != new_resource.frequency ||
current_resource.idle_time != new_resource.idle_time ||
- current_resource.random_delay != new_resource.random_delay ||
- !new_resource.execution_time_limit.include?(current_resource.execution_time_limit) ||
- (new_resource.start_day && start_day_updated?) ||
- (new_resource.start_time && start_time_updated?)
+ random_delay_updated? || execution_time_limit_updated? ||
+ (new_resource.start_day && new_resource.start_day != "N/A" && start_day_updated?) ||
+ (new_resource.start_time && new_resource.start_time != "N/A" && start_time_updated?)
begin
return true if new_resource.day.to_s.casecmp(current_resource.day.to_s) != 0 ||
new_resource.months.to_s.casecmp(current_resource.months.to_s) != 0
@@ -218,9 +242,40 @@ class Chef
false
end
+ # Comparing random_delay values using ISO8601::Duration object Ref: https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
+ # di = ISO8601::Duration.new(65707200)
+ # ds = ISO8601::Duration.new('P65707200S')
+ # dp = ISO8601::Duration.new('P2Y1MT2H')
+ # di == dp # => true
+ # di == ds # => true
+ def random_delay_updated?
+ if new_resource.random_delay.nil?
+ false
+ elsif current_resource.random_delay.nil? && new_resource.random_delay == "PT0S" # when user sets random_dealy to 0 sec
+ false
+ elsif current_resource.random_delay.nil?
+ true
+ else
+ ISO8601::Duration.new(current_resource.random_delay) != ISO8601::Duration.new(new_resource.random_delay)
+ end
+ end
+
+ # Comparing execution_time_limit values using Ref: https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
+ def execution_time_limit_updated?
+ if new_resource.execution_time_limit.nil?
+ false
+ elsif current_resource.execution_time_limit.nil? && new_resource.execution_time_limit == "PT0S" # when user sets random_dealy to 0 sec
+ false
+ elsif current_resource.execution_time_limit.nil?
+ true
+ else
+ ISO8601::Duration.new(current_resource.execution_time_limit) != ISO8601::Duration.new(new_resource.execution_time_limit)
+ end
+ end
+
def start_day_updated?
current_day = DateTime.strptime(current_resource.start_day, convert_system_date_format_to_ruby_date_format)
- new_day = DateTime.parse(new_resource.start_day)
+ new_day = parse_day(new_resource.start_day)
current_day != new_day
end
@@ -230,7 +285,7 @@ class Chef
end
def convert_user_date_to_system_date(date_in_string)
- DateTime.parse(date_in_string).strftime(convert_system_date_format_to_ruby_long_date)
+ parse_day(date_in_string).strftime(convert_system_date_format_to_ruby_long_date)
end
def convert_system_date_format_to_ruby_long_date
@@ -268,6 +323,14 @@ class Chef
@system_short_date_format
end
+ def convert_system_date_to_mm_dd_yyyy(system_date)
+ system_date_format = convert_system_date_format_to_ruby_date_format
+ unless system_date_format == "%m/%d/%Y"
+ system_date = Date.strptime(system_date, system_date_format).strftime("%m/%d/%Y")
+ end
+ system_date
+ end
+
def update_task_xml(options = [])
# random_delay xml element is different for different frequencies
random_delay_xml_element = {
@@ -277,6 +340,7 @@ class Chef
:daily => "Triggers/CalendarTrigger/RandomDelay",
:weekly => "Triggers/CalendarTrigger/RandomDelay",
:monthly => "Triggers/CalendarTrigger/RandomDelay",
+ :none => "Triggers",
}
xml_element_mapping = {
@@ -297,13 +361,19 @@ class Chef
doc = REXML::Document.new(xml_cmd.stdout)
+ if new_resource.frequency == :none
+ doc.root.elements.delete(xml_element_mapping["random_delay"])
+ trigger_element = REXML::Element.new(xml_element_mapping["random_delay"])
+ doc.root.elements.add(trigger_element)
+ end
+
options.each do |option|
- Chef::Log.debug 'Removing former #{option} if any'
+ Chef::Log.debug "Removing former #{option} if any"
doc.root.elements.delete(xml_element_mapping[option])
option_value = new_resource.send("#{option}")
if option_value
- Chef::Log.debug "Setting #option as #option_value"
+ Chef::Log.debug "Setting #{option} as #{option_value}"
split_xml_path = xml_element_mapping[option].split("/") # eg. if xml_element_mapping[option] = "Actions/Exec/WorkingDirectory"
element_name = split_xml_path.last # element_name = "WorkingDirectory"
cwd_element = REXML::Element.new(element_name)
@@ -325,7 +395,6 @@ class Chef
options["RP"] = new_resource.password if new_resource.password
options["IT"] = "" if new_resource.interactive_enabled
options["XML"] = temp_task_file
-
run_schtasks("DELETE", "F" => "")
run_schtasks("CREATE", options)
ensure
@@ -410,7 +479,8 @@ class Chef
task[:idle_time] = root.elements["Settings/IdleSettings/Duration"].text if root.elements["Settings/IdleSettings/Duration"] && task[:on_idle]
- task[:once] = true if !(task[:repetition_interval] || task[:schedule_by_day] || task[:schedule_by_week] || task[:schedule_by_month] || task[:on_logon] || task[:onstart] || task[:on_idle])
+ task[:none] = true if root.elements["Triggers/"] && root.elements["Triggers/"].entries.empty?
+ task[:once] = true if !(task[:repetition_interval] || task[:schedule_by_day] || task[:schedule_by_week] || task[:schedule_by_month] || task[:on_logon] || task[:onstart] || task[:on_idle] || task[:none])
task[:execution_time_limit] = root.elements["Settings/ExecutionTimeLimit"].text if root.elements["Settings/ExecutionTimeLimit"] #by default PT72H
task[:random_delay] = root.elements["Triggers/TimeTrigger/RandomDelay"].text if root.elements["Triggers/TimeTrigger/RandomDelay"]
task[:random_delay] = root.elements["Triggers/CalendarTrigger/RandomDelay"].text if root.elements["Triggers/CalendarTrigger/RandomDelay"]
@@ -481,6 +551,7 @@ class Chef
current_resource.frequency(:onstart) if task_hash[:onstart]
current_resource.frequency(:on_idle) if task_hash[:on_idle]
current_resource.frequency(:once) if task_hash[:once]
+ current_resource.frequency(:none) if task_hash[:none]
end
def set_current_idle_time(idle_time)
@@ -488,6 +559,10 @@ class Chef
current_resource.idle_time(duration.minutes.atom.to_i)
end
+ def parse_day(str)
+ Date.strptime(str, "%m/%d/%Y")
+ end
+
end
end
end
diff --git a/lib/chef/provider/yum_repository.rb b/lib/chef/provider/yum_repository.rb
index 957ee9f0f3..20a7a8e3d2 100644
--- a/lib/chef/provider/yum_repository.rb
+++ b/lib/chef/provider/yum_repository.rb
@@ -47,7 +47,7 @@ class Chef
if new_resource.make_cache
notifies :run, "execute[yum clean metadata #{new_resource.repositoryid}]", :immediately if new_resource.clean_metadata || new_resource.clean_headers
notifies :run, "execute[yum-makecache-#{new_resource.repositoryid}]", :immediately
- notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately
+ notifies :create, "ruby_block[package-cache-reload-#{new_resource.repositoryid}]", :immediately
end
end
@@ -63,9 +63,14 @@ class Chef
only_if { new_resource.enabled }
end
- # reload internal Chef yum cache
- declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
- block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ # reload internal Chef yum/dnf cache
+ declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do
+ if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) ||
+ ( platform_family?("rhel") && node["platform_version"].to_i >= 8 )
+ block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart }
+ else
+ block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ end
action :nothing
end
end
@@ -79,11 +84,16 @@ class Chef
declare_resource(:file, "/etc/yum.repos.d/#{new_resource.repositoryid}.repo") do
action :delete
- notifies :create, "ruby_block[yum-cache-reload-#{new_resource.repositoryid}]", :immediately
+ notifies :create, "ruby_block[package-cache-reload-#{new_resource.repositoryid}]", :immediately
end
- declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
- block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do
+ if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) ||
+ ( platform_family?("rhel") && node["platform_version"].to_i >= 8 )
+ block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart }
+ else
+ block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ end
action :nothing
end
end
@@ -95,8 +105,13 @@ class Chef
only_if { new_resource.enabled }
end
- declare_resource(:ruby_block, "yum-cache-reload-#{new_resource.repositoryid}") do
- block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ declare_resource(:ruby_block, "package-cache-reload-#{new_resource.repositoryid}") do
+ if ( platform?("fedora") && node["platform_version"].to_i >= 22 ) ||
+ ( platform_family?("rhel") && node["platform_version"].to_i >= 8 )
+ block { Chef::Provider::Package::Dnf::PythonHelper.instance.restart }
+ else
+ block { Chef::Provider::Package::Yum::YumCache.instance.reload }
+ end
action :run
end
end
diff --git a/lib/chef/provider/zypper_repository.rb b/lib/chef/provider/zypper_repository.rb
index e6fd917d77..31cf8839b2 100644
--- a/lib/chef/provider/zypper_repository.rb
+++ b/lib/chef/provider/zypper_repository.rb
@@ -18,24 +18,25 @@
require "chef/resource"
require "chef/dsl/declare_resource"
-require "chef/mixin/which"
require "chef/provider/noop"
+require "chef/mixin/shell_out"
require "shellwords"
class Chef
class Provider
class ZypperRepository < Chef::Provider
-
- extend Chef::Mixin::Which
-
- provides :zypper_repository do
- which "zypper"
- end
+ provides :zypper_repository, platform_family: "suse"
def load_current_resource
end
action :create do
+ if new_resource.gpgautoimportkeys
+ install_gpg_key(new_resource.gpgkey)
+ else
+ Chef::Log.debug("'gpgautoimportkeys' property is set to false. Skipping key import.")
+ end
+
declare_resource(:template, "/etc/zypp/repos.d/#{escaped_repo_name}.repo") do
if template_available?(new_resource.source)
source new_resource.source
@@ -51,14 +52,14 @@ class Chef
end
action :delete do
- declare_resource(:execute, "zypper removerepo #{escaped_repo_name}") do
- only_if "zypper lr #{escaped_repo_name}"
+ declare_resource(:execute, "zypper --quiet --non-interactive removerepo #{escaped_repo_name}") do
+ only_if "zypper --quiet lr #{escaped_repo_name}"
end
end
action :refresh do
- declare_resource(:execute, "zypper#{' --gpg-auto-import-keys' if new_resource.gpgautoimportkeys} --quiet --no-confirm refresh --force #{escaped_repo_name}") do
- only_if "zypper lr #{escaped_repo_name}"
+ declare_resource(:execute, "zypper --quiet --non-interactive refresh --force #{escaped_repo_name}") do
+ only_if "zypper --quiet lr #{escaped_repo_name}"
end
end
@@ -66,14 +67,101 @@ class Chef
alias_method :action_remove, :action_delete
# zypper repos are allowed to have spaces in the names
+ # @return [String] escaped repo string
def escaped_repo_name
Shellwords.escape(new_resource.repo_name)
end
+ # return the specified cookbook name or the cookbook containing the
+ # resource.
+ #
+ # @return [String] name of the cookbook
+ def cookbook_name
+ new_resource.cookbook || new_resource.cookbook_name
+ end
+
+ # determine if a template file is available in the current run
+ # @param [String] path the path to the template file
+ #
+ # @return [Boolean] template file exists or doesn't
def template_available?(path)
- !path.nil? && run_context.has_template_in_cookbook?(new_resource.cookbook_name, path)
+ !path.nil? && run_context.has_template_in_cookbook?(cookbook_name, path)
+ end
+
+ # determine if a cookbook file is available in the run
+ # @param [String] path the path to the template file
+ #
+ # @return [Boolean] cookbook file exists or doesn't
+ def has_cookbook_file?(fn)
+ run_context.has_cookbook_file_in_cookbook?(cookbook_name, fn)
+ end
+
+ # Given the provided key URI determine what kind of chef resource we need
+ # to fetch the key
+ # @param [String] uri the uri of the gpg key (local path or http URL)
+ #
+ # @raise [Chef::Exceptions::FileNotFound] Key isn't remote or found in the current run
+ #
+ # @return [Symbol] :remote_file or :cookbook_file
+ def key_type(uri)
+ if uri.start_with?("http")
+ Chef::Log.debug("Will use :remote_file resource to cache the gpg key locally")
+ :remote_file
+ elsif has_cookbook_file?(uri)
+ Chef::Log.debug("Will use :cookbook_file resource to cache the gpg key locally")
+ :cookbook_file
+ else
+ raise Chef::Exceptions::FileNotFound, "Cannot determine location of gpgkey. Must start with 'http' or be a file managed by Chef."
+ end
end
+ # is the provided key already installed
+ # @param [String] key_path the path to the key on the local filesystem
+ #
+ # @return [boolean] is the key already known by rpm
+ def key_installed?(key_path)
+ so = shell_out("rpm -qa gpg-pubkey*")
+ # expected output & match: http://rubular.com/r/RdF7EcXEtb
+ status = /gpg-pubkey-#{key_fingerprint(key_path)}/.match(so.stdout)
+ Chef::Log.debug("GPG key at #{key_path} is known by rpm? #{status ? "true" : "false"}")
+ status
+ end
+
+ # extract the gpg key fingerprint from a local file
+ # @param [String] key_path the path to the key on the local filesystem
+ #
+ # @return [String] the fingerprint of the key
+ def key_fingerprint(key_path)
+ so = shell_out!("gpg --with-fingerprint #{key_path}")
+ # expected output and match: http://rubular.com/r/BpfMjxySQM
+ fingerprint = /pub\s*\S*\/(\S*)/.match(so.stdout)[1].downcase
+ Chef::Log.debug("GPG fingerprint of key at #{key_path} is #{fingerprint}")
+ fingerprint
+ end
+
+ # install the provided gpg key
+ # @param [String] uri the uri of the local or remote gpg key
+ def install_gpg_key(uri)
+ unless uri
+ Chef::Log.debug("'gpgkey' property not provided or set to nil. Skipping key import.")
+ return
+ end
+
+ cached_keyfile = ::File.join(Chef::Config[:file_cache_path], uri.split("/")[-1])
+
+ declare_resource(key_type(new_resource.gpgkey), cached_keyfile) do
+ source uri
+ mode "0644"
+ sensitive new_resource.sensitive
+ action :create
+ end
+
+ declare_resource(:execute, "import gpg key from #{new_resource.gpgkey}") do
+ command "/bin/rpm --import #{cached_keyfile}"
+ not_if { key_installed?(cached_keyfile) }
+ action :run
+ end
+ end
end
end
end
diff --git a/lib/chef/providers.rb b/lib/chef/providers.rb
index a3332477e7..507203fd28 100644
--- a/lib/chef/providers.rb
+++ b/lib/chef/providers.rb
@@ -24,12 +24,10 @@ require "chef/provider/cookbook_file"
require "chef/provider/cron"
require "chef/provider/cron/solaris"
require "chef/provider/cron/aix"
-require "chef/provider/deploy"
require "chef/provider/directory"
require "chef/provider/dsc_script"
require "chef/provider/dsc_resource"
require "chef/provider/env"
-require "chef/provider/erl_call"
require "chef/provider/execute"
require "chef/provider/file"
require "chef/provider/git"
@@ -131,9 +129,6 @@ require "chef/provider/mount/aix"
require "chef/provider/mount/solaris"
require "chef/provider/mount/windows"
-require "chef/provider/deploy/revision"
-require "chef/provider/deploy/timestamped"
-
require "chef/provider/remote_file/ftp"
require "chef/provider/remote_file/sftp"
require "chef/provider/remote_file/http"
diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb
index 5436e3ceb3..77e735bbce 100644
--- a/lib/chef/resource.rb
+++ b/lib/chef/resource.rb
@@ -536,11 +536,6 @@ class Chef
property :ignore_failure, [ TrueClass, FalseClass ], default: false, desired_state: false
#
- # Equivalent to #ignore_failure.
- #
- alias :epic_fail :ignore_failure
-
- #
# Make this resource into an exact (shallow) copy of the other resource.
#
# @param resource [Chef::Resource] The resource to copy from.
@@ -596,7 +591,7 @@ class Chef
elsif remaining_retries > 0
events.resource_failed_retriable(self, action, remaining_retries, e)
remaining_retries -= 1
- Chef::Log.info("Retrying execution of #{self}, #{remaining_retries} attempt(s) left")
+ Chef::Log.info("Retrying execution of #{self}, #{remaining_retries} attempt#{"s" if remaining_retries > 1} left")
sleep retry_delay
retry
else
@@ -861,7 +856,7 @@ class Chef
# @return [Array<Symbol>] The list of actions this Resource is allowed to
# have.
#
- attr_accessor :allowed_actions
+ attr_writer :allowed_actions
def allowed_actions(value = NOT_PASSED)
if value != NOT_PASSED
self.allowed_actions = value
@@ -1179,8 +1174,8 @@ class Chef
# Internal Resource Interface (for Chef)
#
- FORBIDDEN_IVARS = [:@run_context, :@not_if, :@only_if, :@enclosing_provider]
- HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider]
+ FORBIDDEN_IVARS = [:@run_context, :@not_if, :@only_if, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message]
+ HIDDEN_IVARS = [:@allowed_actions, :@resource_name, :@source_line, :@run_context, :@name, :@not_if, :@only_if, :@elapsed_time, :@enclosing_provider, :@description, :@introduced, :@examples, :@validation_message]
include Chef::Mixin::ConvertToClassName
extend Chef::Mixin::ConvertToClassName
@@ -1379,6 +1374,27 @@ class Chef
end
end
+ def self.description(description = "NOT_PASSED")
+ if description != "NOT_PASSED"
+ @description = description
+ end
+ @description
+ end
+
+ def self.introduced(introduced = "NOT_PASSED")
+ if introduced != "NOT_PASSED"
+ @introduced = introduced
+ end
+ @introduced
+ end
+
+ def self.examples(examples = "NOT_PASSED")
+ if examples != "NOT_PASSED"
+ @examples = examples
+ end
+ @examples
+ end
+
#
# The cookbook in which this Resource was defined (if any).
#
diff --git a/lib/chef/resource/action_class.rb b/lib/chef/resource/action_class.rb
index dce3be3244..1bb3decb75 100644
--- a/lib/chef/resource/action_class.rb
+++ b/lib/chef/resource/action_class.rb
@@ -1,6 +1,6 @@
#
# Author:: John Keiser (<jkeiser@chef.io)
-# Copyright:: Copyright 2015-2017, Chef Software Inc.
+# Copyright:: Copyright 2015-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -40,7 +40,7 @@ class Chef
# We clear desired state in the copy, because it is supposed to be actual state.
# We keep identity properties and non-desired-state, which are assumed to be
# "control" values like `recurse: true`
- current_resource.class.properties.each do |name, property|
+ current_resource.class.properties.each_value do |property|
if property.desired_state? && !property.identity? && !property.name_property?
property.reset(current_resource)
end
diff --git a/lib/chef/resource/apt_package.rb b/lib/chef/resource/apt_package.rb
index 8397f84c71..51e38834b6 100644
--- a/lib/chef/resource/apt_package.rb
+++ b/lib/chef/resource/apt_package.rb
@@ -21,11 +21,13 @@ require "chef/provider/package/apt"
class Chef
class Resource
+ # Use the apt_package resource to manage packages on Debian and Ubuntu platforms.
class AptPackage < Chef::Resource::Package
resource_name :apt_package
provides :package, os: "linux", platform_family: "debian"
property :default_release, String, desired_state: false
+ property :overwrite_config_files, [TrueClass, FalseClass], default: false
end
end
diff --git a/lib/chef/resource/apt_preference.rb b/lib/chef/resource/apt_preference.rb
index 603766d76b..87c5a5a016 100644
--- a/lib/chef/resource/apt_preference.rb
+++ b/lib/chef/resource/apt_preference.rb
@@ -20,6 +20,10 @@ require "chef/resource"
class Chef
class Resource
+ # The apt_preference resource allows for the creation of APT preference files. Preference files are used to control
+ # which package versions and sources are prioritized during installation.
+ #
+ # @since 13.3
class AptPreference < Chef::Resource
resource_name :apt_preference
provides :apt_preference
diff --git a/lib/chef/resource/apt_repository.rb b/lib/chef/resource/apt_repository.rb
index 8b69435246..5b81112cbe 100644
--- a/lib/chef/resource/apt_repository.rb
+++ b/lib/chef/resource/apt_repository.rb
@@ -20,23 +20,27 @@ require "chef/resource"
class Chef
class Resource
+ # Use the apt_repository resource to specify additional APT repositories. Adding a new repository will update
+ # APT package cache immediately.
+ #
+ # @since 12.9
class AptRepository < Chef::Resource
resource_name :apt_repository
provides :apt_repository
property :repo_name, String, name_property: true
property :uri, String
- property :distribution, [ String, nil, false ], default: lazy { node["lsb"]["codename"] }, nillable: true, coerce: proc { |x| x ? x : nil }
+ property :distribution, [ String, nil, false ], default: lazy { node["lsb"]["codename"] }, coerce: proc { |x| x ? x : nil }
property :components, Array, default: []
- property :arch, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
+ property :arch, [String, nil, false], default: nil, coerce: proc { |x| x ? x : nil }
property :trusted, [TrueClass, FalseClass], default: false
# whether or not to add the repository as a source repo, too
property :deb_src, [TrueClass, FalseClass], default: false
- property :keyserver, [String, nil, false], default: "keyserver.ubuntu.com", nillable: true, coerce: proc { |x| x ? x : nil }
+ property :keyserver, [String, nil, false], default: "keyserver.ubuntu.com", coerce: proc { |x| x ? x : nil }
property :key, [String, Array, nil, false], default: [], coerce: proc { |x| x ? Array(x) : nil }
- property :key_proxy, [String, nil, false], default: nil, nillable: true, coerce: proc { |x| x ? x : nil }
+ property :key_proxy, [String, nil, false], default: nil, coerce: proc { |x| x ? x : nil }
- property :cookbook, [String, nil, false], default: nil, desired_state: false, nillable: true, coerce: proc { |x| x ? x : nil }
+ property :cookbook, [String, nil, false], default: nil, desired_state: false, coerce: proc { |x| x ? x : nil }
property :cache_rebuild, [TrueClass, FalseClass], default: true, desired_state: false
default_action :add
diff --git a/lib/chef/resource/apt_update.rb b/lib/chef/resource/apt_update.rb
index 67ca7fbfea..0349614ad2 100644
--- a/lib/chef/resource/apt_update.rb
+++ b/lib/chef/resource/apt_update.rb
@@ -20,6 +20,9 @@ require "chef/resource"
class Chef
class Resource
+ # Use the apt_update resource to manage APT repository updates on Debian and Ubuntu platforms.
+ #
+ # @since 12.7
class AptUpdate < Chef::Resource
resource_name :apt_update
provides :apt_update
diff --git a/lib/chef/resource/bash.rb b/lib/chef/resource/bash.rb
index 1238eedc42..ebc4a7790b 100644
--- a/lib/chef/resource/bash.rb
+++ b/lib/chef/resource/bash.rb
@@ -21,6 +21,10 @@ require "chef/provider/script"
class Chef
class Resource
+ # Use the bash resource to execute scripts using the Bash interpreter. This resource may also use any of the actions
+ # and properties that are available to the execute resource. Commands that are executed with this resource are (by
+ # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if
+ # and only_if to guard this resource for idempotence.
class Bash < Chef::Resource::Script
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/batch.rb b/lib/chef/resource/batch.rb
index 10e96839fb..b3c7b17cef 100644
--- a/lib/chef/resource/batch.rb
+++ b/lib/chef/resource/batch.rb
@@ -20,6 +20,11 @@ require "chef/resource/windows_script"
class Chef
class Resource
+ # Use the batch resource to execute a batch script using the cmd.exe interpreter on Windows. The batch resource
+ # creates and executes a temporary file (similar to how the script resource behaves), rather than running the
+ # command inline. Commands that are executed with this resource are (by their nature) not idempotent, as they are
+ # typically unique to the environment in which they are run. Use not_if and only_if to guard this resource for
+ # idempotence.
class Batch < Chef::Resource::WindowsScript
provides :batch, os: "windows"
diff --git a/lib/chef/resource/bff_package.rb b/lib/chef/resource/bff_package.rb
index b14591876a..d91777cb74 100644
--- a/lib/chef/resource/bff_package.rb
+++ b/lib/chef/resource/bff_package.rb
@@ -21,6 +21,10 @@ require "chef/provider/package/aix"
class Chef
class Resource
+ # Use the bff_package resource to manage packages for the AIX platform using the installp utility. When a package is
+ # installed from a local file, it must be added to the node using the remote_file or cookbook_file resources.
+ #
+ # @since 12.0
class BffPackage < Chef::Resource::Package
end
end
diff --git a/lib/chef/resource/breakpoint.rb b/lib/chef/resource/breakpoint.rb
index 81cfd89e5e..5d2c5555be 100644
--- a/lib/chef/resource/breakpoint.rb
+++ b/lib/chef/resource/breakpoint.rb
@@ -20,6 +20,12 @@ require "chef/resource"
class Chef
class Resource
+ # Use the breakpoint resource to add breakpoints to recipes. Run the chef-shell in chef-client mode, and then use
+ # those breakpoints to debug recipes. Breakpoints are ignored by the chef-client during an actual chef-client run.
+ # That said, breakpoints are typically used to debug recipes only when running them in a non-production environment,
+ # after which they are removed from those recipes before the parent cookbook is uploaded to the Chef server.
+ #
+ # @since 12.0
class Breakpoint < Chef::Resource
provides :breakpoint
resource_name :breakpoint
diff --git a/lib/chef/resource/cab_package.rb b/lib/chef/resource/cab_package.rb
index b7acfb0ec9..8f3b3038c4 100644
--- a/lib/chef/resource/cab_package.rb
+++ b/lib/chef/resource/cab_package.rb
@@ -21,24 +21,24 @@ require "chef/mixin/uris"
class Chef
class Resource
+ # Use the cab_package resource to install or remove Microsoft Windows cabinet (.cab) packages.
+ #
+ # @since 12.15
class CabPackage < Chef::Resource::Package
include Chef::Mixin::Uris
+ resource_name :cab_package
provides :cab_package, os: "windows"
allowed_actions :install, :remove
- def initialize(name, run_context = nil)
- super
- @resource_name = :cab_package
- end
-
property :source, String,
coerce: (proc do |s|
unless s.nil?
uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false)
end
- end)
+ end),
+ default: lazy { |r| r.package_name }
end
end
end
diff --git a/lib/chef/resource/chef_gem.rb b/lib/chef/resource/chef_gem.rb
index 7025d74e58..b6bbd0e209 100644
--- a/lib/chef/resource/chef_gem.rb
+++ b/lib/chef/resource/chef_gem.rb
@@ -21,6 +21,18 @@ require "chef/resource/gem_package"
class Chef
class Resource
+ # Use the chef_gem resource to install a gem only for the instance of Ruby that is dedicated to the chef-client.
+ # When a gem is installed from a local file, it must be added to the node using the remote_file or cookbook_file
+ # resources.
+ #
+ # The chef_gem resource works with all of the same properties and options as the gem_package resource, but does not
+ # accept the gem_binary property because it always uses the CurrentGemEnvironment under which the chef-client is
+ # running. In addition to performing actions similar to the gem_package resource, the chef_gem resource does the
+ # following:
+ # - Runs its actions immediately, before convergence, allowing a gem to be used in a recipe immediately after it is
+ # installed
+ # - Runs Gem.clear_paths after the action, ensuring that gem is aware of changes so that it can be required
+ # immediately after it is installed
class ChefGem < Chef::Resource::Package::GemPackage
resource_name :chef_gem
@@ -30,6 +42,7 @@ class Chef
}
property :compile_time, [ true, false ], default: false, desired_state: false
+ # force the resource to compile time if the compile time property has been set
def after_created
if compile_time
Array(action).each do |action|
diff --git a/lib/chef/resource/chocolatey_package.rb b/lib/chef/resource/chocolatey_package.rb
index a443b9a1d7..58bcab8b39 100644
--- a/lib/chef/resource/chocolatey_package.rb
+++ b/lib/chef/resource/chocolatey_package.rb
@@ -20,22 +20,20 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the chocolatey_package resource to manage packages using Chocolatey on the Microsoft Windows platform.
+ #
+ # @since 12.7
class ChocolateyPackage < Chef::Resource::Package
+ resource_name :chocolatey_package
provides :chocolatey_package, os: "windows"
allowed_actions :install, :upgrade, :remove, :uninstall, :purge, :reconfig
- def initialize(name, run_context = nil)
- super
- @resource_name = :chocolatey_package
- end
-
# windows can't take Array options yet
property :options, String
property :package_name, [String, Array], coerce: proc { |x| [x].flatten }
-
property :version, [String, Array], coerce: proc { |x| [x].flatten }
property :returns, [Integer, Array], default: [ 0 ], desired_state: false
end
diff --git a/lib/chef/resource/cookbook_file.rb b/lib/chef/resource/cookbook_file.rb
index 785cf693be..8c3de119e9 100644
--- a/lib/chef/resource/cookbook_file.rb
+++ b/lib/chef/resource/cookbook_file.rb
@@ -24,26 +24,24 @@ require "chef/mixin/securable"
class Chef
class Resource
+ # Use the cookbook_file resource to transfer files from a sub-directory of COOKBOOK_NAME/files/ to a specified path
+ # located on a host that is running the chef-client. The file is selected according to file specificity, which allows
+ # different source files to be used based on the hostname, host platform (operating system, distro, or as appropriate),
+ # or platform version. Files that are located in the COOKBOOK_NAME/files/default sub-directory may be used on any
+ # platform.
+ #
+ # During a chef-client run, the checksum for each local file is calculated and then compared against the checksum for
+ # the same file as it currently exists in the cookbook on the Chef server. A file is not transferred when the checksums
+ # match. Only files that require an update are transferred from the Chef server to a node.
class CookbookFile < Chef::Resource::File
include Chef::Mixin::Securable
- default_action :create
-
- def initialize(name, run_context = nil)
- super
- @provider = Chef::Provider::CookbookFile
- @source = ::File.basename(name)
- @cookbook = nil
- end
+ resource_name :cookbook_file
- def source(source_filename = nil)
- set_or_return(:source, source_filename, :kind_of => [ String, Array ])
- end
-
- def cookbook(cookbook_name = nil)
- set_or_return(:cookbook, cookbook_name, :kind_of => String)
- end
+ property :source, [ String, Array ], default: lazy { ::File.basename(name) }
+ property :cookbook, String
+ default_action :create
end
end
end
diff --git a/lib/chef/resource/cron.rb b/lib/chef/resource/cron.rb
index a76d454bf0..2b70be7bb8 100644
--- a/lib/chef/resource/cron.rb
+++ b/lib/chef/resource/cron.rb
@@ -21,6 +21,8 @@ require "chef/resource"
class Chef
class Resource
+ # Use the cron resource to manage cron entries for time-based job scheduling. Properties for a schedule will default
+ # to * if not provided. The cron resource requires access to a crontab program, typically cron.
class Cron < Chef::Resource
identity_attr :command
diff --git a/lib/chef/resource/csh.rb b/lib/chef/resource/csh.rb
index 4e7c22b660..ef302af6c0 100644
--- a/lib/chef/resource/csh.rb
+++ b/lib/chef/resource/csh.rb
@@ -21,6 +21,10 @@ require "chef/provider/script"
class Chef
class Resource
+ # Use the csh resource to execute scripts using the csh interpreter. This resource may also use any of the actions
+ # and properties that are available to the execute resource. Commands that are executed with this resource are (by
+ # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if
+ # and only_if to guard this resource for idempotence.
class Csh < Chef::Resource::Script
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/deploy.rb b/lib/chef/resource/deploy.rb
deleted file mode 100644
index b8e6a26f97..0000000000
--- a/lib/chef/resource/deploy.rb
+++ /dev/null
@@ -1,443 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# EX:
-# deploy "/my/deploy/dir" do
-# repo "git@github.com/whoami/project"
-# revision "abc123" # or "HEAD" or "TAG_for_1.0" or (subversion) "1234"
-# user "deploy_ninja"
-# enable_submodules true
-# migrate true
-# migration_command "rake db:migrate"
-# environment "RAILS_ENV" => "production", "OTHER_ENV" => "foo"
-# shallow_clone true
-# depth 1
-# action :deploy # or :rollback
-# restart_command "touch tmp/restart.txt"
-# git_ssh_wrapper "wrap-ssh4git.sh"
-# scm_provider Chef::Provider::Git # is the default, for svn: Chef::Provider::Subversion
-# svn_username "whoami"
-# svn_password "supersecret"
-# end
-
-require "chef/resource/scm"
-
-class Chef
- class Resource
-
- # Deploy: Deploy apps from a source control repository.
- #
- # Callbacks:
- # Callbacks can be a block or a string. If given a block, the code
- # is evaluated as an embedded recipe, and run at the specified
- # point in the deploy process. If given a string, the string is taken as
- # a path to a callback file/recipe. Paths are evaluated relative to the
- # release directory. Callback files can contain chef code (resources, etc.)
- #
- class Deploy < Chef::Resource
-
- identity_attr :repository
-
- state_attrs :deploy_to, :revision
-
- default_action :deploy
- allowed_actions :force_deploy, :deploy, :rollback
-
- def initialize(name, run_context = nil)
- super
- @deploy_to = name
- @environment = nil
- @repository_cache = "cached-copy"
- @copy_exclude = []
- @purge_before_symlink = %w{log tmp/pids public/system}
- @create_dirs_before_symlink = %w{tmp public config}
- @symlink_before_migrate = { "config/database.yml" => "config/database.yml" }
- @symlinks = { "system" => "public/system", "pids" => "tmp/pids", "log" => "log" }
- @revision = "HEAD"
- @migrate = false
- @rollback_on_error = false
- @remote = "origin"
- @enable_submodules = false
- @shallow_clone = false
- @depth = nil
- @scm_provider = Chef::Provider::Git
- @svn_force_export = false
- @additional_remotes = Hash[]
- @keep_releases = 5
- @enable_checkout = true
- @checkout_branch = "deploy"
- end
-
- # where the checked out/cloned code goes
- def destination
- @destination ||= shared_path + "/#{@repository_cache}"
- end
-
- # where shared stuff goes, i.e., logs, tmp, etc. goes here
- def shared_path
- @shared_path ||= @deploy_to + "/shared"
- end
-
- # where the deployed version of your code goes
- def current_path
- @current_path ||= @deploy_to + "/current"
- end
-
- def depth(arg = @shallow_clone ? 5 : nil)
- set_or_return(
- :depth,
- arg,
- :kind_of => [ Integer ]
- )
- end
-
- # note: deploy_to is your application "meta-root."
- def deploy_to(arg = nil)
- set_or_return(
- :deploy_to,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def repo(arg = nil)
- set_or_return(
- :repo,
- arg,
- :kind_of => [ String ]
- )
- end
- alias :repository :repo
-
- def remote(arg = nil)
- set_or_return(
- :remote,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def role(arg = nil)
- set_or_return(
- :role,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def restart_command(arg = nil, &block)
- arg ||= block
- set_or_return(
- :restart_command,
- arg,
- :kind_of => [ String, Proc ]
- )
- end
- alias :restart :restart_command
-
- def migrate(arg = nil)
- set_or_return(
- :migrate,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def migration_command(arg = nil)
- set_or_return(
- :migration_command,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def rollback_on_error(arg = nil)
- set_or_return(
- :rollback_on_error,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def user(arg = nil)
- set_or_return(
- :user,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def group(arg = nil)
- set_or_return(
- :group,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def enable_submodules(arg = nil)
- set_or_return(
- :enable_submodules,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def shallow_clone(arg = nil)
- set_or_return(
- :shallow_clone,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def repository_cache(arg = nil)
- set_or_return(
- :repository_cache,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def copy_exclude(arg = nil)
- set_or_return(
- :copy_exclude,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def revision(arg = nil)
- set_or_return(
- :revision,
- arg,
- :kind_of => [ String ]
- )
- end
- alias :branch :revision
-
- def git_ssh_wrapper(arg = nil)
- set_or_return(
- :git_ssh_wrapper,
- arg,
- :kind_of => [ String ]
- )
- end
- alias :ssh_wrapper :git_ssh_wrapper
-
- def svn_username(arg = nil)
- set_or_return(
- :svn_username,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def svn_password(arg = nil)
- set_or_return(
- :svn_password,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def svn_arguments(arg = nil)
- set_or_return(
- :svn_arguments,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def svn_info_args(arg = nil)
- set_or_return(
- :svn_arguments,
- arg,
- :kind_of => [ String ])
- end
-
- def scm_provider(arg = nil)
- klass = if arg.kind_of?(String) || arg.kind_of?(Symbol)
- lookup_provider_constant(arg)
- else
- arg
- end
- set_or_return(
- :scm_provider,
- klass,
- :kind_of => [ Class ]
- )
- end
-
- # This is to support "provider :revision" without deprecation warnings.
- # Do NOT copy this.
- def self.provider_base
- Chef::Provider::Deploy
- end
-
- def svn_force_export(arg = nil)
- set_or_return(
- :svn_force_export,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def environment(arg = nil)
- if arg.is_a?(String)
- Chef::Log.debug "Setting RAILS_ENV, RACK_ENV, and MERB_ENV to `#{arg}'"
- Chef::Log.warn "[DEPRECATED] please modify your deploy recipe or attributes to set the environment using a hash"
- arg = { "RAILS_ENV" => arg, "MERB_ENV" => arg, "RACK_ENV" => arg }
- end
- set_or_return(
- :environment,
- arg,
- :kind_of => [ Hash ]
- )
- end
-
- # The number of old release directories to keep around after cleanup
- def keep_releases(arg = nil)
- [set_or_return(
- :keep_releases,
- arg,
- :kind_of => [ Integer ]), 1].max
- end
-
- # An array of paths, relative to your app's root, to be purged from a
- # SCM clone/checkout before symlinking. Use this to get rid of files and
- # directories you want to be shared between releases.
- # Default: ["log", "tmp/pids", "public/system"]
- def purge_before_symlink(arg = nil)
- set_or_return(
- :purge_before_symlink,
- arg,
- :kind_of => Array
- )
- end
-
- # An array of paths, relative to your app's root, where you expect dirs to
- # exist before symlinking. This runs after #purge_before_symlink, so you
- # can use this to recreate dirs that you had previously purged.
- # For example, if you plan to use a shared directory for pids, and you
- # want it to be located in $APP_ROOT/tmp/pids, you could purge tmp,
- # then specify tmp here so that the tmp directory will exist when you
- # symlink the pids directory in to the current release.
- # Default: ["tmp", "public", "config"]
- def create_dirs_before_symlink(arg = nil)
- set_or_return(
- :create_dirs_before_symlink,
- arg,
- :kind_of => Array
- )
- end
-
- # A Hash of shared/dir/path => release/dir/path. This attribute determines
- # which files and dirs in the shared directory get symlinked to the current
- # release directory, and where they go. If you have a directory
- # $shared/pids that you would like to symlink as $current_release/tmp/pids
- # you specify it as "pids" => "tmp/pids"
- # Default {"system" => "public/system", "pids" => "tmp/pids", "log" => "log"}
- def symlinks(arg = nil)
- set_or_return(
- :symlinks,
- arg,
- :kind_of => Hash
- )
- end
-
- # A Hash of shared/dir/path => release/dir/path. This attribute determines
- # which files in the shared directory get symlinked to the current release
- # directory and where they go. Unlike map_shared_files, these are symlinked
- # *before* any migration is run.
- # For a rails/merb app, this is used to link in a known good database.yml
- # (with the production db password) before running migrate.
- # Default {"config/database.yml" => "config/database.yml"}
- def symlink_before_migrate(arg = nil)
- set_or_return(
- :symlink_before_migrate,
- arg,
- :kind_of => Hash
- )
- end
-
- # Callback fires before migration is run.
- def before_migrate(arg = nil, &block)
- arg ||= block
- set_or_return(:before_migrate, arg, :kind_of => [Proc, String])
- end
-
- # Callback fires before symlinking
- def before_symlink(arg = nil, &block)
- arg ||= block
- set_or_return(:before_symlink, arg, :kind_of => [Proc, String])
- end
-
- # Callback fires before restart
- def before_restart(arg = nil, &block)
- arg ||= block
- set_or_return(:before_restart, arg, :kind_of => [Proc, String])
- end
-
- # Callback fires after restart
- def after_restart(arg = nil, &block)
- arg ||= block
- set_or_return(:after_restart, arg, :kind_of => [Proc, String])
- end
-
- def additional_remotes(arg = nil)
- set_or_return(
- :additional_remotes,
- arg,
- :kind_of => Hash
- )
- end
-
- def enable_checkout(arg = nil)
- set_or_return(
- :enable_checkout,
- arg,
- :kind_of => [TrueClass, FalseClass]
- )
- end
-
- def checkout_branch(arg = nil)
- set_or_return(
- :checkout_branch,
- arg,
- :kind_of => String
- )
- end
-
- # FIXME The Deploy resource may be passed to an SCM provider as its
- # resource. The SCM provider knows that SCM resources can specify a
- # timeout for SCM operations. The deploy resource must therefore support
- # a timeout method, but the timeout it describes is for SCM operations,
- # not the overall deployment. This is potentially confusing.
- def timeout(arg = nil)
- set_or_return(
- :timeout,
- arg,
- :kind_of => Integer
- )
- end
-
- end
- end
-end
diff --git a/lib/chef/resource/deploy_revision.rb b/lib/chef/resource/deploy_revision.rb
deleted file mode 100644
index 41046ec288..0000000000
--- a/lib/chef/resource/deploy_revision.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-class Chef
- class Resource
-
- # Convenience class for using the deploy resource with the revision
- # deployment strategy (provider)
- class DeployRevision < Chef::Resource::Deploy
- end
-
- class DeployBranch < Chef::Resource::DeployRevision
- end
-
- end
-end
diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb
index faad659668..b989b3ecde 100644
--- a/lib/chef/resource/directory.rb
+++ b/lib/chef/resource/directory.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Seth Chisamore (<schisamo@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");
@@ -19,14 +19,16 @@
#
require "chef/resource"
-require "chef/provider/directory"
require "chef/mixin/securable"
class Chef
class Resource
+ # Use the directory resource to manage a directory, which is a hierarchy of folders that comprises all of the
+ # information stored on a computer. The root directory is the top-level, under which the rest of the directory
+ # is organized. The directory resource uses the name property to specify the path to a location in a directory.
+ # Typically, permission to access that location in the directory is required.
class Directory < Chef::Resource
-
- identity_attr :path
+ resource_name :directory
state_attrs :group, :mode, :owner
@@ -35,28 +37,8 @@ class Chef
default_action :create
allowed_actions :create, :delete
- def initialize(name, run_context = nil)
- super
- @path = name
- @recursive = false
- end
-
- def recursive(arg = nil)
- set_or_return(
- :recursive,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def path(arg = nil)
- set_or_return(
- :path,
- arg,
- :kind_of => String
- )
- end
-
+ property :path, String, name_property: true, identity: true
+ property :recursive, [ TrueClass, FalseClass ], default: false
end
end
end
diff --git a/lib/chef/resource/dnf_package.rb b/lib/chef/resource/dnf_package.rb
index d92dc12ec7..0e09d90d43 100644
--- a/lib/chef/resource/dnf_package.rb
+++ b/lib/chef/resource/dnf_package.rb
@@ -21,6 +21,11 @@ require "chef/mixin/shell_out"
class Chef
class Resource
+ # Use the dnf_package resource to install, upgrade, and remove packages with DNF for Fedora platforms. The dnf_package
+ # resource is able to resolve provides data for packages much like DNF can do when it is run from the command line.
+ # This allows a variety of options for installing packages, like minimum versions, virtual provides, and library names.
+ #
+ # @since 12.18
class DnfPackage < Chef::Resource::Package
extend Chef::Mixin::Which
extend Chef::Mixin::ShellOut
@@ -29,8 +34,15 @@ class Chef
allowed_actions :install, :upgrade, :remove, :purge, :reconfig, :lock, :unlock, :flush_cache
- provides :package, platform_family: %w{rhel fedora amazon} do
- which("dnf") && shell_out("rpm -q dnf").stdout =~ /^dnf-[1-9]/
+ # all rhel variants >= 8 will use DNF
+ provides :package, platform_family: "rhel", platform_version: ">= 8"
+
+ # fedora >= 22 uses DNF
+ provides :package, platform: "fedora", platform_version: ">= 22"
+
+ # amazon will eventually use DNF
+ provides :package, platform: "amazon" do
+ which("dnf")
end
provides :dnf_package
diff --git a/lib/chef/resource/dpkg_package.rb b/lib/chef/resource/dpkg_package.rb
index 9ff3239884..c73fc506ad 100644
--- a/lib/chef/resource/dpkg_package.rb
+++ b/lib/chef/resource/dpkg_package.rb
@@ -20,6 +20,8 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the dpkg_package resource to manage packages for the dpkg platform. When a package is installed from a local
+ # file, it must be added to the node using the remote_file or cookbook_file resources.
class DpkgPackage < Chef::Resource::Package
resource_name :dpkg_package
provides :dpkg_package, os: "linux"
diff --git a/lib/chef/resource/dsc_resource.rb b/lib/chef/resource/dsc_resource.rb
index d3b579e428..0840b9bca1 100644
--- a/lib/chef/resource/dsc_resource.rb
+++ b/lib/chef/resource/dsc_resource.rb
@@ -19,6 +19,11 @@ require "chef/dsl/powershell"
class Chef
class Resource
+ # The dsc_resource resource allows any DSC resource to be used in a Chef recipe, as well as any custom resources
+ # that have been added to your Windows PowerShell environment. Microsoft frequently adds new resources to the DSC
+ # resource collection.
+ #
+ # @since 12.2
class DscResource < Chef::Resource
provides :dsc_resource, os: "windows"
diff --git a/lib/chef/resource/dsc_script.rb b/lib/chef/resource/dsc_script.rb
index 7da29a651a..cea52e422b 100644
--- a/lib/chef/resource/dsc_script.rb
+++ b/lib/chef/resource/dsc_script.rb
@@ -21,9 +21,15 @@ require "chef/dsl/powershell"
class Chef
class Resource
+ # Many DSC resources are comparable to built-in Chef resources. For example, both DSC and Chef have file, package,
+ # and service resources. The dsc_script resource is most useful for those DSC resources that do not have a direct
+ # comparison to a resource in Chef, such as the Archive resource, a custom DSC resource, an existing DSC script
+ # that performs an important task, and so on. Use the dsc_script resource to embed the code that defines a DSC
+ # configuration directly within a Chef recipe.
class DscScript < Chef::Resource
include Chef::DSL::Powershell
+ resource_name :dsc_script
provides :dsc_script, os: "windows"
default_action :run
diff --git a/lib/chef/resource/env.rb b/lib/chef/resource/env.rb
index 746369f02d..12133f4368 100644
--- a/lib/chef/resource/env.rb
+++ b/lib/chef/resource/env.rb
@@ -19,7 +19,10 @@
class Chef
class Resource
+ # Use the env resource to manage environment keys in Microsoft Windows. After an environment key is set, Microsoft
+ # Windows must be restarted before the environment key will be available to the Task Scheduler.
class Env < Chef::Resource
+ resource_name :env
provides :env, os: "windows"
default_action :create
diff --git a/lib/chef/resource/erl_call.rb b/lib/chef/resource/erl_call.rb
deleted file mode 100644
index 3e317676a5..0000000000
--- a/lib/chef/resource/erl_call.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# Author:: Joe Williams (<joe@joetify.com>)
-# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2009-2016, Joe Williams
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "chef/resource"
-require "chef/provider/erl_call"
-
-class Chef
- class Resource
- class ErlCall < Chef::Resource
-
- # erl_call : http://erlang.org/doc/man/erl_call.html
-
- identity_attr :code
-
- default_action :run
-
- def initialize(name, run_context = nil)
- super
-
- @code = "q()." # your erlang code goes here
- @cookie = nil # cookie of the erlang node
- @distributed = false # if you want to have a distributed erlang node
- @name_type = "sname" # type of erlang hostname name or sname
- @node_name = "chef@localhost" # the erlang node hostname
- end
-
- def code(arg = nil)
- set_or_return(
- :code,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def cookie(arg = nil)
- set_or_return(
- :cookie,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def distributed(arg = nil)
- set_or_return(
- :distributed,
- arg,
- :kind_of => [ TrueClass, FalseClass ]
- )
- end
-
- def name_type(arg = nil)
- set_or_return(
- :name_type,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def node_name(arg = nil)
- set_or_return(
- :node_name,
- arg,
- :kind_of => [ String ]
- )
- end
-
- end
- end
-end
diff --git a/lib/chef/resource/execute.rb b/lib/chef/resource/execute.rb
index ba1b8ae6e3..616195deee 100644
--- a/lib/chef/resource/execute.rb
+++ b/lib/chef/resource/execute.rb
@@ -22,6 +22,9 @@ require "chef/provider/execute"
class Chef
class Resource
+ # Use the execute resource to execute a single command. Commands that are executed with this resource are (by their
+ # nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if
+ # to guard this resource for idempotence.
class Execute < Chef::Resource
identity_attr :command
@@ -130,7 +133,8 @@ class Chef
property :password, String, sensitive: true
- property :sensitive, [ TrueClass, FalseClass ], default: false, coerce: proc { |x| password ? true : x }
+ # lazy used to set default value of sensitive to true if password is set
+ property :sensitive, [ TrueClass, FalseClass ], default: lazy { |r| r.password ? true : false }
property :elevated, [ TrueClass, FalseClass ], default: false
diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb
index 5c275a574f..787992fc24 100644
--- a/lib/chef/resource/file.rb
+++ b/lib/chef/resource/file.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
-# Copyright:: Copyright 2008-2016 Chef Software, Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +25,7 @@ require "pathname"
class Chef
class Resource
+ # Use the file resource to manage files directly on a node.
class File < Chef::Resource
include Chef::Mixin::Securable
@@ -43,7 +44,7 @@ class Chef
# mutate the new_resource.checksum which would change the
# user intent in the new_resource if the resource is reused.
#
- # @returns [String] Checksum of the file we actually rendered
+ # @return [String] Checksum of the file we actually rendered
attr_accessor :final_checksum
default_action :create
diff --git a/lib/chef/resource/file/verification.rb b/lib/chef/resource/file/verification.rb
index 079e6dc201..ed6fce2e5c 100644
--- a/lib/chef/resource/file/verification.rb
+++ b/lib/chef/resource/file/verification.rb
@@ -119,6 +119,16 @@ class Chef
v = verification_class.new(@parent_resource, @command, @command_opts, &@block)
v.verify(path, opts)
end
+
+ def to_s
+ if @block
+ "<Proc>"
+ elsif @command.is_a?(Symbol)
+ "#{@command.inspect} (#{Chef::Resource::File::Verification.lookup(@command).name})"
+ elsif @command.is_a?(String)
+ @command
+ end
+ end
end
end
end
diff --git a/lib/chef/resource/freebsd_package.rb b/lib/chef/resource/freebsd_package.rb
index ecaff95244..caaba29129 100644
--- a/lib/chef/resource/freebsd_package.rb
+++ b/lib/chef/resource/freebsd_package.rb
@@ -26,25 +26,33 @@ require "chef/mixin/shell_out"
class Chef
class Resource
+ # Use the freebsd_package resource to manage packages for the FreeBSD platform.
class FreebsdPackage < Chef::Resource::Package
include Chef::Mixin::ShellOut
resource_name :freebsd_package
provides :package, platform: "freebsd"
+ # make sure we assign the appropriate underlying providers based on what
+ # package managers exist on this FreeBSD system or the source of the package
+ #
+ # @return [void]
def after_created
assign_provider
end
+ # Is the system at least version 1000017 or is the make variable WITH_PKGNG set
+ #
+ # @return [Boolean] do we support pkgng
def supports_pkgng?
ships_with_pkgng? || !!shell_out_compact!("make", "-V", "WITH_PKGNG", :env => nil).stdout.match(/yes/i)
end
private
+ # It was not until __FreeBSD_version 1000017 that pkgng became
+ # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
def ships_with_pkgng?
- # It was not until __FreeBSD_version 1000017 that pkgng became
- # the default binary package manager. See '/usr/ports/Mk/bsd.port.mk'.
node[:os_version].to_i >= 1000017
end
diff --git a/lib/chef/resource/gem_package.rb b/lib/chef/resource/gem_package.rb
index fc162a6033..8e3a426035 100644
--- a/lib/chef/resource/gem_package.rb
+++ b/lib/chef/resource/gem_package.rb
@@ -20,6 +20,8 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the gem_package resource to manage gem packages that are only included in recipes. When a package is installed
+ # from a local file, it must be added to the node using the remote_file or cookbook_file resources.
class GemPackage < Chef::Resource::Package
resource_name :gem_package
diff --git a/lib/chef/resource/git.rb b/lib/chef/resource/git.rb
index 4799b54d3d..ac4f027552 100644
--- a/lib/chef/resource/git.rb
+++ b/lib/chef/resource/git.rb
@@ -20,6 +20,8 @@ require "chef/resource/scm"
class Chef
class Resource
+ # Use the git resource to manage source control resources that exist in a git repository. git version 1.6.5 (or higher)
+ # is required to use all of the functionality in the git resource.
class Git < Chef::Resource::Scm
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/group.rb b/lib/chef/resource/group.rb
index d3a4a1ce89..69a3827a5c 100644
--- a/lib/chef/resource/group.rb
+++ b/lib/chef/resource/group.rb
@@ -19,6 +19,7 @@
class Chef
class Resource
+ # Use the group resource to manage a local group.
class Group < Chef::Resource
identity_attr :group_name
diff --git a/lib/chef/resource/homebrew_package.rb b/lib/chef/resource/homebrew_package.rb
index c2d0a65c5b..6174a31079 100644
--- a/lib/chef/resource/homebrew_package.rb
+++ b/lib/chef/resource/homebrew_package.rb
@@ -23,6 +23,9 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the homebrew_package resource to manage packages for the macOS platform.
+ #
+ # @since 12.0
class HomebrewPackage < Chef::Resource::Package
resource_name :homebrew_package
provides :package, os: "darwin"
diff --git a/lib/chef/resource/http_request.rb b/lib/chef/resource/http_request.rb
index 9fac3562f3..9d8fce9b22 100644
--- a/lib/chef/resource/http_request.rb
+++ b/lib/chef/resource/http_request.rb
@@ -22,6 +22,8 @@ require "chef/provider/http_request"
class Chef
class Resource
+ # Use the http_request resource to send an HTTP request (GET, PUT, POST, DELETE, HEAD, or OPTIONS) with an arbitrary
+ # message. This resource is often useful when custom callbacks are necessary.
class HttpRequest < Chef::Resource
identity_attr :url
diff --git a/lib/chef/resource/ifconfig.rb b/lib/chef/resource/ifconfig.rb
index 3673311348..e9ef47d95b 100644
--- a/lib/chef/resource/ifconfig.rb
+++ b/lib/chef/resource/ifconfig.rb
@@ -21,163 +21,36 @@ require "chef/resource"
class Chef
class Resource
+ # use the ifconfig resource to manage interfaces on *nix systems
+ #
+ # @example set a static ip on eth1
+ # ifconfig '33.33.33.80' do
+ # device 'eth1'
+ # end
class Ifconfig < Chef::Resource
-
- identity_attr :device
+ resource_name :ifconfig
state_attrs :inet_addr, :mask
default_action :add
allowed_actions :add, :delete, :enable, :disable
- def initialize(name, run_context = nil)
- super
- @target = name
- @hwaddr = nil
- @mask = nil
- @inet_addr = nil
- @bcast = nil
- @mtu = nil
- @metric = nil
- @device = nil
- @onboot = nil
- @network = nil
- @bootproto = nil
- @onparent = nil
- @ethtool_opts = nil
- @bonding_opts = nil
- @master = nil
- @slave = nil
- end
-
- def target(arg = nil)
- set_or_return(
- :target,
- arg,
- :kind_of => String
- )
- end
-
- def device(arg = nil)
- set_or_return(
- :device,
- arg,
- :kind_of => String
- )
- end
-
- def hwaddr(arg = nil)
- set_or_return(
- :hwaddr,
- arg,
- :kind_of => String
- )
- end
-
- def inet_addr(arg = nil)
- set_or_return(
- :inet_addr,
- arg,
- :kind_of => String
- )
- end
-
- def bcast(arg = nil)
- set_or_return(
- :bcast,
- arg,
- :kind_of => String
- )
- end
-
- def mask(arg = nil)
- set_or_return(
- :mask,
- arg,
- :kind_of => String
- )
- end
-
- def mtu(arg = nil)
- set_or_return(
- :mtu,
- arg,
- :kind_of => String
- )
- end
-
- def metric(arg = nil)
- set_or_return(
- :metric,
- arg,
- :kind_of => String
- )
- end
-
- def onboot(arg = nil)
- set_or_return(
- :onboot,
- arg,
- :kind_of => String
- )
- end
-
- def network(arg = nil)
- set_or_return(
- :network,
- arg,
- :kind_of => String
- )
- end
-
- def bootproto(arg = nil)
- set_or_return(
- :bootproto,
- arg,
- :kind_of => String
- )
- end
-
- def onparent(arg = nil)
- set_or_return(
- :onparent,
- arg,
- :kind_of => String
- )
- end
-
- def ethtool_opts(arg = nil)
- set_or_return(
- :ethtool_opts,
- arg,
- :kind_of => String
- )
- end
-
- def bonding_opts(arg = nil)
- set_or_return(
- :bonding_opts,
- arg,
- :kind_of => String
- )
- end
-
- def master(arg = nil)
- set_or_return(
- :master,
- arg,
- :kind_of => String
- )
- end
-
- def slave(arg = nil)
- set_or_return(
- :slave,
- arg,
- :kind_of => String
- )
- end
+ property :target, String, name_property: true
+ property :hwaddr, String
+ property :mask, String
+ property :inet_addr, String
+ property :bcast, String
+ property :mtu, String
+ property :metric, String
+ property :device, String, identity: true
+ property :onboot, String
+ property :network, String
+ property :bootproto, String
+ property :onparent, String
+ property :ethtool_opts, String
+ property :bonding_opts, String
+ property :master, String
+ property :slave, String
end
-
end
end
diff --git a/lib/chef/resource/ips_package.rb b/lib/chef/resource/ips_package.rb
index 4d2c957e17..296919dc1c 100644
--- a/lib/chef/resource/ips_package.rb
+++ b/lib/chef/resource/ips_package.rb
@@ -21,6 +21,7 @@ require "chef/provider/package/ips"
class Chef
class Resource
+ # Use the ips_package resource to manage packages (using Image Packaging System (IPS)) on the Solaris 11 platform.
class IpsPackage < ::Chef::Resource::Package
resource_name :ips_package
provides :package, os: "solaris2"
diff --git a/lib/chef/resource/ksh.rb b/lib/chef/resource/ksh.rb
index 3097156329..8024f0d6bd 100644
--- a/lib/chef/resource/ksh.rb
+++ b/lib/chef/resource/ksh.rb
@@ -20,6 +20,12 @@ require "chef/resource/script"
class Chef
class Resource
+ # Use the ksh resource to execute scripts using the Korn shell (ksh) interpreter. This resource may also use any
+ # f the actions and properties that are available to the execute resource. Commands that are executed with this
+ # resource are (by their nature) not idempotent, as they are typically unique to the environment in which they are
+ # run. Use not_if and only_if to guard this resource for idempotence.
+ #
+ # @since 12.6
class Ksh < Chef::Resource::Script
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/launchd.rb b/lib/chef/resource/launchd.rb
index 3fba76e220..121af1555c 100644
--- a/lib/chef/resource/launchd.rb
+++ b/lib/chef/resource/launchd.rb
@@ -17,19 +17,20 @@
#
require "chef/resource"
-require "chef/provider/launchd"
class Chef
class Resource
+ # Use the launchd resource to manage system-wide services (daemons) and per-user services (agents) on the macOS platform.
+ #
+ # @since 12.8
class Launchd < Chef::Resource
+ resource_name :launchd
provides :launchd, os: "darwin"
- identity_attr :label
-
default_action :create
allowed_actions :create, :create_if_missing, :delete, :enable, :disable, :restart
- property :label, String, default: lazy { name }, identity: true
+ property :label, String, identity: true, name_property: true
property :backup, [Integer, FalseClass]
property :cookbook, String
property :group, [String, Integer]
diff --git a/lib/chef/resource/link.rb b/lib/chef/resource/link.rb
index 5717ec7bad..d51d42b506 100644
--- a/lib/chef/resource/link.rb
+++ b/lib/chef/resource/link.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,8 +22,19 @@ require "chef/mixin/securable"
class Chef
class Resource
+ # Use the link resource to create symbolic or hard links.
+ #
+ # A symbolic link—sometimes referred to as a soft link—is a directory entry that associates a file name with a string
+ # that contains an absolute or relative path to a file on any file system. In other words, “a file that contains a path
+ # that points to another file.” A symbolic link creates a new file with a new inode that points to the inode location
+ # of the original file.
+ #
+ # A hard link is a directory entry that associates a file with another file in the same file system. In other words,
+ # “multiple directory entries to the same file.” A hard link creates a new file that points to the same inode as the
+ # original file.
class Link < Chef::Resource
include Chef::Mixin::Securable
+ resource_name :link
identity_attr :target_file
diff --git a/lib/chef/resource/log.rb b/lib/chef/resource/log.rb
index 8f7879872f..66c8e820f4 100644
--- a/lib/chef/resource/log.rb
+++ b/lib/chef/resource/log.rb
@@ -18,59 +18,32 @@
#
require "chef/resource"
-require "chef/provider/log"
class Chef
class Resource
+ # Use the log resource to create log entries. The log resource behaves like any other resource: built into the resource
+ # collection during the compile phase, and then run during the execution phase. (To create a log entry that is not built
+ # into the resource collection, use Chef::Log instead of the log resource.)
+ #
+ # Allows logging a :debug, :info, :warn, and :error levels
+ # Defaults to :info level
+ #
+ # @example logging at default info level
+ # log "your string to log"
+ #
+ # @example logging at specified debug level
+ # log "a debug string" do
+ # level :debug
+ # end
+ #
class Log < Chef::Resource
+ resource_name :log
- identity_attr :message
+ property :message, String, name_property: true, identity: true
+ property :level, Symbol, equal_to: [ :debug, :info, :warn, :error, :fatal ], default: :info
+ allowed_actions :write
default_action :write
-
- # Sends a string from a recipe to a log provider
- #
- # log "some string to log" do
- # level :info # (default) also supports :warn, :debug, and :error
- # end
- #
- # === Example
- # log "your string to log"
- #
- # or
- #
- # log "a debug string" { level :debug }
- #
-
- # Initialize log resource with a name as the string to log
- #
- # === Parameters
- # name<String>:: Message to log
- # collection<Array>:: Collection of included recipes
- # node<Chef::Node>:: Node where resource will be used
- def initialize(name, run_context = nil)
- super
- @level = :info
- @message = name
- end
-
- def message(arg = nil)
- set_or_return(
- :message,
- arg,
- :kind_of => String
- )
- end
-
- # <Symbol> Log level, one of :debug, :info, :warn, :error or :fatal
- def level(arg = nil)
- set_or_return(
- :level,
- arg,
- :equal_to => [ :debug, :info, :warn, :error, :fatal ]
- )
- end
-
end
end
end
diff --git a/lib/chef/resource/lwrp_base.rb b/lib/chef/resource/lwrp_base.rb
index b12ac98673..0e4c3f826c 100644
--- a/lib/chef/resource/lwrp_base.rb
+++ b/lib/chef/resource/lwrp_base.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software, Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -41,8 +41,6 @@ class Chef
include Chef::Mixin::ConvertToClassName
include Chef::Mixin::FromFile
- attr_accessor :loaded_lwrps
-
def build_from_file(cookbook_name, filename, run_context)
if LWRPBase.loaded_lwrps[filename]
Chef::Log.debug("Custom resource #{filename} from cookbook #{cookbook_name} has already been loaded! Skipping the reload.")
@@ -102,6 +100,7 @@ class Chef
protected
+ attr_writer :loaded_lwrps
def loaded_lwrps
@loaded_lwrps ||= {}
end
diff --git a/lib/chef/resource/macports_package.rb b/lib/chef/resource/macports_package.rb
index 3685334c17..e787529f48 100644
--- a/lib/chef/resource/macports_package.rb
+++ b/lib/chef/resource/macports_package.rb
@@ -20,6 +20,7 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the macports_package resource to manage packages for the macOS platform.
class MacportsPackage < Chef::Resource::Package
resource_name :macports_package
end
diff --git a/lib/chef/resource/mdadm.rb b/lib/chef/resource/mdadm.rb
index df6e705f15..354582d1cf 100644
--- a/lib/chef/resource/mdadm.rb
+++ b/lib/chef/resource/mdadm.rb
@@ -21,6 +21,10 @@ require "chef/resource"
class Chef
class Resource
+ # Use the mdadm resource to manage RAID devices in a Linux environment using the mdadm utility. The mdadm resource
+ # will create and assemble an array, but it will not create the config file that is used to persist the array upon
+ # reboot. If the config file is required, it must be done by specifying a template with the correct array layout,
+ # and then by using the mount provider to create a file systems table (fstab) entry.
class Mdadm < Chef::Resource
identity_attr :raid_device
diff --git a/lib/chef/resource/mount.rb b/lib/chef/resource/mount.rb
index 7e601b861a..1a1f8c0565 100644
--- a/lib/chef/resource/mount.rb
+++ b/lib/chef/resource/mount.rb
@@ -21,6 +21,7 @@ require "chef/resource"
class Chef
class Resource
+ # Use the mount resource to manage a mounted file system.
class Mount < Chef::Resource
identity_attr :device
@@ -34,6 +35,8 @@ class Chef
property :supports, Hash, default: lazy { { remount: false } },
coerce: proc { |x| x.is_a?(Array) ? x.each_with_object({}) { |i, m| m[i] = true } : x }
+ property :password, String, sensitive: true
+
def initialize(name, run_context = nil)
super
@mount_point = name
@@ -151,14 +154,6 @@ class Chef
)
end
- def password(arg = nil)
- set_or_return(
- :password,
- arg,
- :kind_of => [ String ]
- )
- end
-
def domain(arg = nil)
set_or_return(
:domain,
diff --git a/lib/chef/resource/msu_package.rb b/lib/chef/resource/msu_package.rb
index 753992c185..77eeed898f 100644
--- a/lib/chef/resource/msu_package.rb
+++ b/lib/chef/resource/msu_package.rb
@@ -21,26 +21,25 @@ require "chef/mixin/uris"
class Chef
class Resource
+ # Use the msu_package resource to install Microsoft Update(MSU) packages on Microsoft Windows machines.
+ #
+ # @since 12.17
class MsuPackage < Chef::Resource::Package
include Chef::Mixin::Uris
+ resource_name :msu_package
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
+ default_action :install
property :source, String,
coerce: (proc do |s|
unless s.nil?
uri_scheme?(s) ? s : Chef::Util::PathHelper.canonical_path(s, false)
end
- end)
+ end),
+ default: lazy { |r| r.package_name }
property :checksum, String, desired_state: false
end
end
diff --git a/lib/chef/resource/ohai.rb b/lib/chef/resource/ohai.rb
index 6fffecf16e..f2534413ea 100644
--- a/lib/chef/resource/ohai.rb
+++ b/lib/chef/resource/ohai.rb
@@ -19,6 +19,8 @@
class Chef
class Resource
+ # Use the ohai resource to reload the Ohai configuration on a node. This allows recipes that change system attributes
+ # (like a recipe that adds a user) to refer to those attributes later on during the chef-client run.
class Ohai < Chef::Resource
resource_name :ohai
provides :ohai
diff --git a/lib/chef/resource/openbsd_package.rb b/lib/chef/resource/openbsd_package.rb
index d0f9fe877f..e5cdefe684 100644
--- a/lib/chef/resource/openbsd_package.rb
+++ b/lib/chef/resource/openbsd_package.rb
@@ -25,6 +25,9 @@ require "chef/mixin/shell_out"
class Chef
class Resource
+ # Use the openbsd_package resource to manage packages for the OpenBSD platform.
+ #
+ # @since 12.1
class OpenbsdPackage < Chef::Resource::Package
include Chef::Mixin::ShellOut
diff --git a/lib/chef/resource/openssl_dhparam.rb b/lib/chef/resource/openssl_dhparam.rb
new file mode 100644
index 0000000000..693061f535
--- /dev/null
+++ b/lib/chef/resource/openssl_dhparam.rb
@@ -0,0 +1,59 @@
+#
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ # a resource for generating dhparam.pem files.
+ # If a valid dhparam.pem file is found at the specified location, no new
+ # file will be created. If a file is found at the specified location but it
+ # is not a valid dhparam file, it will be overwritten.
+ #
+ # @since 14.0
+ class OpensslDhparam < Chef::Resource
+ require "chef/mixin/openssl_helper"
+ include Chef::Mixin::OpenSSLHelper
+
+ resource_name :openssl_dhparam
+
+ property :path, String, name_property: true
+ property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048
+ property :generator, equal_to: [2, 5], default: 2
+ property :owner, [String, nil]
+ property :group, [String, nil]
+ property :mode, [Integer, String], default: "0640"
+
+ action :create do
+ unless dhparam_pem_valid?(new_resource.path)
+ converge_by("Create a dhparam file #{new_resource.path}") do
+ dhparam_content = gen_dhparam(new_resource.key_length, new_resource.generator).to_pem
+
+ declare_resource(:file, new_resource.path) do
+ action :create
+ owner new_resource.owner unless new_resource.owner.nil?
+ group new_resource.group unless new_resource.group.nil?
+ mode new_resource.mode
+ sensitive true
+ content dhparam_content
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/openssl_rsa_private_key.rb b/lib/chef/resource/openssl_rsa_private_key.rb
new file mode 100644
index 0000000000..4b0bae2fd0
--- /dev/null
+++ b/lib/chef/resource/openssl_rsa_private_key.rb
@@ -0,0 +1,69 @@
+#
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ # A resource for generating rsa private key files.
+ # If a valid rsa key file can be opened at the specified location, no new file
+ # will be created. If the RSA key file cannot be opened, either because it
+ # does not exist or because the password to the RSA key file does not match
+ # the password in the recipe, it will be overwritten.
+ #
+ # @since 14.0
+ class OpensslRsaPrivateKey < Chef::Resource
+ require "chef/mixin/openssl_helper"
+ include Chef::Mixin::OpenSSLHelper
+
+ resource_name :openssl_rsa_private_key
+ provides :openssl_rsa_private_key
+ provides :openssl_rsa_key # legacy cookbook resource name
+
+ property :path, String, name_property: true
+ property :key_length, equal_to: [1024, 2048, 4096, 8192], default: 2048
+ property :key_pass, String
+ property :key_cipher, String, default: "des3", equal_to: OpenSSL::Cipher.ciphers
+ property :owner, [String, nil]
+ property :group, [String, nil]
+ property :mode, [Integer, String], default: "0600"
+ property :force, [true, false], default: false
+
+ action :create do
+ return if new_resource.force || priv_key_file_valid?(new_resource.path, new_resource.key_pass)
+
+ converge_by("create #{new_resource.key_length} bit RSA key #{new_resource.path}") do
+ if new_resource.key_pass
+ unencrypted_rsa_key = gen_rsa_priv_key(new_resource.key_length)
+ rsa_key_content = encrypt_rsa_key(unencrypted_rsa_key, new_resource.key_pass, new_resource.key_cipher)
+ else
+ rsa_key_content = gen_rsa_priv_key(new_resource.key_length).to_pem
+ end
+
+ declare_resource(:file, new_resource.path) do
+ action :create
+ owner new_resource.owner unless new_resource.owner.nil?
+ group new_resource.group unless new_resource.group.nil?
+ mode new_resource.mode
+ sensitive true
+ content rsa_key_content
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/openssl_rsa_public_key.rb b/lib/chef/resource/openssl_rsa_public_key.rb
new file mode 100644
index 0000000000..5ab7206938
--- /dev/null
+++ b/lib/chef/resource/openssl_rsa_public_key.rb
@@ -0,0 +1,56 @@
+#
+# Copyright:: Copyright 2009-2018, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "chef/resource"
+
+class Chef
+ class Resource
+ # A resource for generating rsa public key files given a rsa private key.
+ #
+ # @since 14.0
+ class OpensslRsaPublicKey < Chef::Resource
+ require "chef/mixin/openssl_helper"
+ include Chef::Mixin::OpenSSLHelper
+
+ resource_name :openssl_rsa_public_key
+
+ property :path, String, name_property: true
+ property :private_key_path, String
+ property :private_key_content, String
+ property :private_key_pass, String
+ property :owner, [String, nil]
+ property :group, [String, nil]
+ property :mode, [Integer, String], default: "0640"
+
+ action :create do
+ raise ArgumentError, "You cannot specify both 'private_key_path' and 'private_key_content' properties at the same time." if new_resource.private_key_path && new_resource.private_key_content
+ raise ArgumentError, "You must specify the private key with either 'private_key_path' or 'private_key_content' properties." unless new_resource.private_key_path || new_resource.private_key_content
+ raise "#{new_resource.private_key_path} not a valid private RSA key or password is invalid" unless priv_key_file_valid?((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass)
+
+ rsa_key_content = gen_rsa_pub_key((new_resource.private_key_path || new_resource.private_key_content), new_resource.private_key_pass)
+
+ declare_resource(:file, new_resource.path) do
+ action :create
+ owner new_resource.owner unless new_resource.owner.nil?
+ group new_resource.group unless new_resource.group.nil?
+ mode new_resource.mode
+ content rsa_key_content
+ end
+ end
+ end
+ end
+end
diff --git a/lib/chef/resource/osx_profile.rb b/lib/chef/resource/osx_profile.rb
index 8142e1fd96..1d13a8851e 100644
--- a/lib/chef/resource/osx_profile.rb
+++ b/lib/chef/resource/osx_profile.rb
@@ -20,6 +20,12 @@ require "chef/resource"
class Chef
class Resource
+ # Use the osx_profile resource to manage configuration profiles (.mobileconfig files)
+ # on the macOS platform. The osx_profile resource installs profiles by using
+ # the uuidgen library to generate a unique ProfileUUID, and then using the
+ # profiles command to install the profile on the system.
+ #
+ # @since 12.7
class OsxProfile < Chef::Resource
provides :osx_profile, os: "darwin"
provides :osx_config_profile, os: "darwin"
@@ -29,46 +35,10 @@ class Chef
default_action :install
allowed_actions :install, :remove
- def initialize(name, run_context = nil)
- super
- @profile_name = name
- @profile = nil
- @identifier = nil
- @path = nil
- end
-
- def profile_name(arg = nil)
- set_or_return(
- :profile_name,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def profile(arg = nil)
- set_or_return(
- :profile,
- arg,
- :kind_of => [ String, Hash ]
- )
- end
-
- def identifier(arg = nil)
- set_or_return(
- :identifier,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def path(arg = nil)
- set_or_return(
- :path,
- arg,
- :kind_of => [ String ]
- )
- end
-
+ property :profile_name, String, name_property: true
+ property :profile, [ String, Hash ]
+ property :identifier, String
+ property :path, String
end
end
end
diff --git a/lib/chef/resource/package.rb b/lib/chef/resource/package.rb
index 5647f203d2..60810fd5ad 100644
--- a/lib/chef/resource/package.rb
+++ b/lib/chef/resource/package.rb
@@ -21,6 +21,12 @@ require "chef/resource"
class Chef
class Resource
+ # Use the package resource to manage packages. When the package is installed from a local file (such as with RubyGems,
+ # dpkg, or RPM Package Manager), the file must be added to the node using the remote_file or cookbook_file resources.
+ #
+ # This resource is the base resource for several other resources used for package management on specific platforms.
+ # While it is possible to use each of these specific resources, it is recommended to use the package resource as often
+ # as possible.
class Package < Chef::Resource
resource_name :package
diff --git a/lib/chef/resource/pacman_package.rb b/lib/chef/resource/pacman_package.rb
index 66b39d164d..73d8afb0de 100644
--- a/lib/chef/resource/pacman_package.rb
+++ b/lib/chef/resource/pacman_package.rb
@@ -20,6 +20,7 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the pacman_package resource to manage packages (using pacman) on the Arch Linux platform.
class PacmanPackage < Chef::Resource::Package
resource_name :pacman_package
provides :pacman_package, os: "linux"
diff --git a/lib/chef/resource/paludis_package.rb b/lib/chef/resource/paludis_package.rb
index 31c0f31b8c..6bc598e4ee 100644
--- a/lib/chef/resource/paludis_package.rb
+++ b/lib/chef/resource/paludis_package.rb
@@ -21,6 +21,9 @@ require "chef/provider/package/paludis"
class Chef
class Resource
+ # Use the paludis_package resource to manage packages for the Paludis platform.
+ #
+ # @since 12.1
class PaludisPackage < Chef::Resource::Package
resource_name :paludis_package
provides :paludis_package, os: "linux"
diff --git a/lib/chef/resource/perl.rb b/lib/chef/resource/perl.rb
index 60af0e92da..c00246ac6b 100644
--- a/lib/chef/resource/perl.rb
+++ b/lib/chef/resource/perl.rb
@@ -21,6 +21,10 @@ require "chef/provider/script"
class Chef
class Resource
+ # Use the perl resource to execute scripts using the Perl interpreter. This resource may also use any of the actions
+ # and properties that are available to the execute resource. Commands that are executed with this resource are (by
+ # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and
+ # only_if to guard this resource for idempotence.
class Perl < Chef::Resource::Script
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/portage_package.rb b/lib/chef/resource/portage_package.rb
index ad66c7b42b..a2bc516711 100644
--- a/lib/chef/resource/portage_package.rb
+++ b/lib/chef/resource/portage_package.rb
@@ -20,6 +20,7 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the portage_package resource to manage packages for the Gentoo platform.
class PortagePackage < Chef::Resource::Package
resource_name :portage_package
def initialize(name, run_context = nil)
diff --git a/lib/chef/resource/powershell_package.rb b/lib/chef/resource/powershell_package.rb
index 4d658d3cc5..05c59acf73 100644
--- a/lib/chef/resource/powershell_package.rb
+++ b/lib/chef/resource/powershell_package.rb
@@ -20,6 +20,11 @@ require "chef/mixin/uris"
class Chef
class Resource
+ # Use the powershell_package resource to install and manage packages via the Powershell Package Manager for the
+ # Microsoft Windows platform. The powershell_package resource requires administrative access, and a source must be
+ # configured in the Powershell Package Manager via the Register-PackageSource command
+ #
+ # @since 12.16
class PowershellPackage < Chef::Resource::Package
include Chef::Mixin::Uris
diff --git a/lib/chef/resource/powershell_script.rb b/lib/chef/resource/powershell_script.rb
index b2bd6e718e..8ff58cfeab 100644
--- a/lib/chef/resource/powershell_script.rb
+++ b/lib/chef/resource/powershell_script.rb
@@ -19,6 +19,14 @@ require "chef/resource/windows_script"
class Chef
class Resource
+ # Use the powershell_script resource to execute a script using the Windows PowerShell interpreter, much like how the
+ # script and script-based resources—bash, csh, perl, python, and ruby—are used. The powershell_script is specific to
+ # the Microsoft Windows platform and the Windows PowerShell interpreter.
+ #
+ # The powershell_script resource creates and executes a temporary file (similar to how the script resource behaves),
+ # rather than running the command inline. Commands that are executed with this resource are (by their nature) not
+ # idempotent, as they are typically unique to the environment in which they are run. Use not_if and only_if to guard
+ # this resource for idempotence.
class PowershellScript < Chef::Resource::WindowsScript
provides :powershell_script, os: "windows"
diff --git a/lib/chef/resource/python.rb b/lib/chef/resource/python.rb
index bcad3d090b..8c9e74217a 100644
--- a/lib/chef/resource/python.rb
+++ b/lib/chef/resource/python.rb
@@ -20,6 +20,10 @@ require "chef/provider/script"
class Chef
class Resource
+ # Use the python resource to execute scripts using the Python interpreter. This resource may also use any of the actions
+ # and properties that are available to the execute resource. Commands that are executed with this resource are (by
+ # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and
+ # only_if to guard this resource for idempotence.
class Python < Chef::Resource::Script
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/reboot.rb b/lib/chef/resource/reboot.rb
index 519defa602..e93c7f53c5 100644
--- a/lib/chef/resource/reboot.rb
+++ b/lib/chef/resource/reboot.rb
@@ -18,31 +18,25 @@
require "chef/resource"
-# In using this resource via notifications, it's important to *only* use
-# immediate notifications. Delayed notifications produce unintuitive and
-# probably undesired results.
class Chef
class Resource
+ # Use the reboot resource to reboot a node, a necessary step with some
+ # installations on certain platforms. This resource is supported for use on
+ # the Microsoft Windows, macOS, and Linux platforms.
+ #
+ # In using this resource via notifications, it's important to *only* use
+ # immediate notifications. Delayed notifications produce unintuitive and
+ # probably undesired results.
+ #
+ # @since 12.0
class Reboot < Chef::Resource
- allowed_actions :request_reboot, :reboot_now, :cancel
-
- def initialize(name, run_context = nil)
- super
- @provider = Chef::Provider::Reboot
-
- @reason = "Reboot by Chef"
- @delay_mins = 0
+ resource_name :reboot
- # no default action.
- end
-
- def reason(arg = nil)
- set_or_return(:reason, arg, :kind_of => String)
- end
+ allowed_actions :request_reboot, :reboot_now, :cancel
+ default_action :nothing # make sure people are quite clear what they want
- def delay_mins(arg = nil)
- set_or_return(:delay_mins, arg, :kind_of => Integer)
- end
+ property :reason, String, default: "Reboot by Chef"
+ property :delay_mins, Integer, default: 0
end
end
end
diff --git a/lib/chef/resource/registry_key.rb b/lib/chef/resource/registry_key.rb
index 549897bb1d..565ff278ea 100644
--- a/lib/chef/resource/registry_key.rb
+++ b/lib/chef/resource/registry_key.rb
@@ -21,6 +21,7 @@ require "chef/digester"
class Chef
class Resource
+ # Use the registry_key resource to create and delete registry keys in Microsoft Windows.
class RegistryKey < Chef::Resource
identity_attr :key
state_attrs :values
diff --git a/lib/chef/resource/remote_directory.rb b/lib/chef/resource/remote_directory.rb
index 6e2928f3eb..b165606c79 100644
--- a/lib/chef/resource/remote_directory.rb
+++ b/lib/chef/resource/remote_directory.rb
@@ -23,6 +23,9 @@ require "chef/mixin/securable"
class Chef
class Resource
+ # Use the remote_directory resource to incrementally transfer a directory from a cookbook to a node. The director
+ # that is copied from the cookbook should be located under COOKBOOK_NAME/files/default/REMOTE_DIRECTORY. The
+ # remote_directory resource will obey file specificity.
class RemoteDirectory < Chef::Resource::Directory
include Chef::Mixin::Securable
diff --git a/lib/chef/resource/remote_file.rb b/lib/chef/resource/remote_file.rb
index 25586af702..d2c2622524 100644
--- a/lib/chef/resource/remote_file.rb
+++ b/lib/chef/resource/remote_file.rb
@@ -25,6 +25,8 @@ require "chef/mixin/uris"
class Chef
class Resource
+ # Use the remote_file resource to transfer a file from a remote location using file specificity. This resource is
+ # similar to the file resource.
class RemoteFile < Chef::Resource::File
include Chef::Mixin::Securable
@@ -137,6 +139,8 @@ class Chef
property :remote_password, String, sensitive: true
+ property :authentication, equal_to: [:remote, :local], default: :remote
+
def after_created
validate_identity_platform(remote_user, remote_password, remote_domain)
identity = qualify_user(remote_user, remote_password, remote_domain)
diff --git a/lib/chef/resource/resource_notification.rb b/lib/chef/resource/resource_notification.rb
index ee90064a17..6ede2fc346 100644
--- a/lib/chef/resource/resource_notification.rb
+++ b/lib/chef/resource/resource_notification.rb
@@ -20,16 +20,24 @@ require "chef/resource"
class Chef
class Resource
+ # @author Tyler Ball
+ # @attr [Resource] resource the Chef resource object to notify to
+ # @attr [Action] action the action to notify
+ # @attr [Resource] notifying_resource the Chef resource performing the notification
class Notification
attr_accessor :resource, :action, :notifying_resource
def initialize(resource, action, notifying_resource)
@resource = resource
- @action = action
+ @action = action&.to_sym
@notifying_resource = notifying_resource
end
+ # Is the current notification a duplicate of another notification
+ #
+ # @param [Notification] another notification object to compare to
+ # @return [Boolean] does the resource match
def duplicates?(other_notification)
unless other_notification.respond_to?(:resource) && other_notification.respond_to?(:action)
msg = "only duck-types of Chef::Resource::Notification can be checked for duplication "\
@@ -41,6 +49,9 @@ class Chef
# If resource and/or notifying_resource is not a resource object, this will look them up in the resource collection
# and fix the references from strings to actual Resource objects.
+ # @param [ResourceCollection] resource_collection
+ #
+ # @return [void]
def resolve_resource_reference(resource_collection)
return resource if resource.kind_of?(Chef::Resource) && notifying_resource.kind_of?(Chef::Resource)
@@ -55,6 +66,9 @@ class Chef
# This will look up the resource if it is not a Resource Object. It will complain if it finds multiple
# resources, can't find a resource, or gets invalid syntax.
+ # @param [ResourceCollection] resource_collection
+ #
+ # @return [void]
def fix_resource_reference(resource_collection)
matching_resource = resource_collection.find(resource)
if Array(matching_resource).size > 1
@@ -84,6 +98,9 @@ is defined near #{notifying_resource.source_line}
# This will look up the notifying_resource if it is not a Resource Object. It will complain if it finds multiple
# resources, can't find a resource, or gets invalid syntax.
+ # @param [ResourceCollection] resource_collection
+ #
+ # @return [void]
def fix_notifier_reference(resource_collection)
matching_notifier = resource_collection.find(notifying_resource)
if Array(matching_notifier).size > 1
diff --git a/lib/chef/resource/route.rb b/lib/chef/resource/route.rb
index 9412d28dce..922535f885 100644
--- a/lib/chef/resource/route.rb
+++ b/lib/chef/resource/route.rb
@@ -21,6 +21,7 @@ require "chef/resource"
class Chef
class Resource
+ # Use the route resource to manage the system routing table in a Linux environment.
class Route < Chef::Resource
default_action :add
allowed_actions :add, :delete
diff --git a/lib/chef/resource/rpm_package.rb b/lib/chef/resource/rpm_package.rb
index c93dfecaf5..3760412a77 100644
--- a/lib/chef/resource/rpm_package.rb
+++ b/lib/chef/resource/rpm_package.rb
@@ -21,6 +21,7 @@ require "chef/provider/package/rpm"
class Chef
class Resource
+ # Use the rpm_package resource to manage packages for the RPM Package Manager platform.
class RpmPackage < Chef::Resource::Package
resource_name :rpm_package
provides :rpm_package, os: %w{linux aix}
diff --git a/lib/chef/resource/ruby.rb b/lib/chef/resource/ruby.rb
index 91805a1db6..300405f89e 100644
--- a/lib/chef/resource/ruby.rb
+++ b/lib/chef/resource/ruby.rb
@@ -21,6 +21,10 @@ require "chef/provider/script"
class Chef
class Resource
+ # Use the ruby resource to execute scripts using the Ruby interpreter. This resource may also use any of the actions
+ # and properties that are available to the execute resource. Commands that are executed with this resource are (by
+ # their nature) not idempotent, as they are typically unique to the environment in which they are run. Use not_if and
+ # only_if to guard this resource for idempotence.
class Ruby < Chef::Resource::Script
def initialize(name, run_context = nil)
super
diff --git a/lib/chef/resource/ruby_block.rb b/lib/chef/resource/ruby_block.rb
index 87a4cfb7c5..89b90ae70b 100644
--- a/lib/chef/resource/ruby_block.rb
+++ b/lib/chef/resource/ruby_block.rb
@@ -22,6 +22,9 @@ require "chef/provider/ruby_block"
class Chef
class Resource
+ # Use the ruby_block resource to execute Ruby code during a chef-client run. Ruby code in the ruby_block resource is
+ # evaluated with other resources during convergence, whereas Ruby code outside of a ruby_block resource is evaluated
+ # before other resources, as the recipe is compiled.
class RubyBlock < Chef::Resource
default_action :run
allowed_actions :create, :run
diff --git a/lib/chef/resource/script.rb b/lib/chef/resource/script.rb
index 5039e2d8fe..a7191360ca 100644
--- a/lib/chef/resource/script.rb
+++ b/lib/chef/resource/script.rb
@@ -22,6 +22,10 @@ require "chef/provider/script"
class Chef
class Resource
+ # Use the script resource to execute scripts using a specified interpreter, such as Bash, csh, Perl, Python, or Ruby.
+ # This resource may also use any of the actions and properties that are available to the execute resource. Commands
+ # that are executed with this resource are (by their nature) not idempotent, as they are typically unique to the
+ # environment in which they are run. Use not_if and only_if to guard this resource for idempotence.
class Script < Chef::Resource::Execute
identity_attr :name
diff --git a/lib/chef/resource/service.rb b/lib/chef/resource/service.rb
index 83e44c9d30..dc23155b59 100644
--- a/lib/chef/resource/service.rb
+++ b/lib/chef/resource/service.rb
@@ -22,6 +22,7 @@ require "shellwords"
class Chef
class Resource
+ # Use the service resource to manage a service.
class Service < Chef::Resource
identity_attr :service_name
diff --git a/lib/chef/resource/smartos_package.rb b/lib/chef/resource/smartos_package.rb
index 87173ccfa9..9e79cace3f 100644
--- a/lib/chef/resource/smartos_package.rb
+++ b/lib/chef/resource/smartos_package.rb
@@ -21,6 +21,7 @@ require "chef/provider/package/smartos"
class Chef
class Resource
+ # Use the smartos_package resource to manage packages for the SmartOS platform.
class SmartosPackage < Chef::Resource::Package
resource_name :smartos_package
provides :package, os: "solaris2", platform_family: "smartos"
diff --git a/lib/chef/resource/solaris_package.rb b/lib/chef/resource/solaris_package.rb
index d0f8c144af..24215bb456 100644
--- a/lib/chef/resource/solaris_package.rb
+++ b/lib/chef/resource/solaris_package.rb
@@ -22,6 +22,7 @@ require "chef/provider/package/solaris"
class Chef
class Resource
+ # The solaris_package resource is used to manage packages for the Solaris platform.
class SolarisPackage < Chef::Resource::Package
resource_name :solaris_package
provides :package, os: "solaris2", platform_family: "nexentacore"
diff --git a/lib/chef/resource/subversion.rb b/lib/chef/resource/subversion.rb
index 9966614eeb..473a48cefd 100644
--- a/lib/chef/resource/subversion.rb
+++ b/lib/chef/resource/subversion.rb
@@ -21,6 +21,7 @@ require "chef/resource/scm"
class Chef
class Resource
+ # Use the subversion resource to manage source control resources that exist in a Subversion repository.
class Subversion < Chef::Resource::Scm
allowed_actions :force_export
diff --git a/lib/chef/resource/systemd_unit.rb b/lib/chef/resource/systemd_unit.rb
index 1a19a7d682..baf7e4cfa8 100644
--- a/lib/chef/resource/systemd_unit.rb
+++ b/lib/chef/resource/systemd_unit.rb
@@ -1,6 +1,6 @@
#
# Author:: Nathan Williams (<nath.e.will@gmail.com>)
-# Copyright:: Copyright 2016, Nathan Williams
+# Copyright:: Copyright 2016-2018, Nathan Williams
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,12 +21,16 @@ require "iniparse"
class Chef
class Resource
+ # Use the systemd_unit resource to create, manage, and run systemd units.
+ #
+ # @since 12.11
class SystemdUnit < Chef::Resource
resource_name :systemd_unit
default_action :nothing
allowed_actions :create, :delete,
- :enable, :disable,
+ :preset, :revert,
+ :enable, :disable, :reenable,
:mask, :unmask,
:start, :stop,
:restart, :reload,
@@ -46,6 +50,9 @@ class Chef
default: true, desired_state: false
property :verify, [TrueClass, FalseClass],
default: true, desired_state: false
+ property :unit_name, String, desired_state: false,
+ identity: true,
+ name_property: true
def to_ini
case content
diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb
index 896aa71340..4b5b82effb 100644
--- a/lib/chef/resource/template.rb
+++ b/lib/chef/resource/template.rb
@@ -24,6 +24,15 @@ require "chef/mixin/securable"
class Chef
class Resource
+ # A cookbook template is an Embedded Ruby (ERB) template that is used to dynamically generate static text files.
+ # Templates may contain Ruby expressions and statements, and are a great way to manage configuration files. Use the
+ # template resource to add cookbook templates to recipes; place the corresponding Embedded Ruby (ERB) template file
+ # in a cookbook’s /templates directory.
+ #
+ # Use the template resource to manage the contents of a file using an Embedded Ruby (ERB) template by transferring
+ # files from a sub-directory of COOKBOOK_NAME/templates/ to a specified path located on a host that is running the
+ # chef-client. This resource includes actions and properties from the file resource. Template files managed by the
+ # template resource follow the same file specificity rules as the remote_file and file resources.
class Template < Chef::Resource::File
include Chef::Mixin::Securable
diff --git a/lib/chef/resource/timestamped_deploy.rb b/lib/chef/resource/timestamped_deploy.rb
deleted file mode 100644
index 1d6b07a719..0000000000
--- a/lib/chef/resource/timestamped_deploy.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-class Chef
- class Resource
- # Convenience class for using the deploy resource with the timestamped
- # deployment strategy (provider)
- class TimestampedDeploy < Chef::Resource::Deploy
- end
- end
-end
diff --git a/lib/chef/resource/user.rb b/lib/chef/resource/user.rb
index 380671113a..39d8159d4f 100644
--- a/lib/chef/resource/user.rb
+++ b/lib/chef/resource/user.rb
@@ -20,6 +20,7 @@ require "chef/resource"
class Chef
class Resource
+ # Use the user resource to add users, update existing users, remove users, and to lock/unlock user passwords.
class User < Chef::Resource
resource_name :user_resource_abstract_base_class # this prevents magickal class name DSL wiring
identity_attr :username
diff --git a/lib/chef/resource/windows_package.rb b/lib/chef/resource/windows_package.rb
index e37bad4b0a..d373e1f19c 100644
--- a/lib/chef/resource/windows_package.rb
+++ b/lib/chef/resource/windows_package.rb
@@ -23,6 +23,8 @@ require "chef/win32/error" if RUBY_PLATFORM =~ /mswin|mingw|windows/
class Chef
class Resource
+ # Use the windows_package resource to manage Microsoft Installer Package (MSI) packages for the Microsoft Windows
+ # platform.
class WindowsPackage < Chef::Resource::Package
include Chef::Mixin::Uris
diff --git a/lib/chef/resource/windows_path.rb b/lib/chef/resource/windows_path.rb
index 5472a7e4fd..7da24a3c06 100644
--- a/lib/chef/resource/windows_path.rb
+++ b/lib/chef/resource/windows_path.rb
@@ -20,21 +20,16 @@ require "chef/resource"
class Chef
class Resource
+ # Use the windows_path resource to manage the path environment variable on Microsoft Windows.
+ #
+ # @since 13.4
class WindowsPath < Chef::Resource
-
- provides :windows_path, os: "windows"
+ resource_name :windows_path
+ provides :windows_path
allowed_actions :add, :remove
default_action :add
- def initialize(name, run_context = nil)
- super
- @resource_name = :windows_path
- @path = name
- @provider = Chef::Provider::WindowsPath
- @action = :add
- end
-
property :path, String, name_property: true
end
end
diff --git a/lib/chef/resource/windows_service.rb b/lib/chef/resource/windows_service.rb
index 405f7f6dbe..4e14b18c20 100644
--- a/lib/chef/resource/windows_service.rb
+++ b/lib/chef/resource/windows_service.rb
@@ -17,10 +17,21 @@
#
require "chef/resource/service"
+require "chef/win32_service_constants"
class Chef
class Resource
+ # Use the windows_service resource to manage a service on the Microsoft Windows platform.
+ #
+ # @since 12.0
class WindowsService < Chef::Resource::Service
+ include Chef::Win32ServiceConstants
+
+ ALLOWED_START_TYPES = {
+ automatic: SERVICE_AUTO_START,
+ manual: SERVICE_DEMAND_START,
+ disabled: SERVICE_DISABLED,
+ }
# Until #1773 is resolved, you need to manually specify the windows_service resource
# to use action :configure_startup and attribute startup_type
@@ -28,44 +39,79 @@ class Chef
provides :windows_service, os: "windows"
provides :service, os: "windows"
- allowed_actions :configure_startup
+ allowed_actions :configure_startup, :create, :delete, :configure
identity_attr :service_name
state_attrs :enabled, :running
- def initialize(name, run_context = nil)
- super
- @startup_type = :automatic
- @run_as_user = ""
- @run_as_password = ""
- end
-
- def startup_type(arg = nil)
- # Set-Service arguments are automatic and manual
- # Win32::Service returns 'auto start' or 'demand start' respectively, which the provider currently uses
- set_or_return(
- :startup_type,
- arg,
- :equal_to => [ :automatic, :manual, :disabled ]
- )
- end
-
- def run_as_user(arg = nil)
- set_or_return(
- :run_as_user,
- arg,
- :kind_of => [ String ]
- )
- end
-
- def run_as_password(arg = nil)
- set_or_return(
- :run_as_password,
- arg,
- :kind_of => [ String ]
- )
- end
+ property :service_name, name_property: true
+
+ # The display name to be used by user interface programs to identify the
+ # service. This string has a maximum length of 256 characters.
+ property :display_name, String, regex: /^.{1,256}$/
+
+ # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L19-L29
+ property :desired_access, Integer, default: SERVICE_ALL_ACCESS
+
+ # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L31-L41
+ property :service_type, Integer, default: SERVICE_WIN32_OWN_PROCESS
+
+ # Valid options:
+ # - :automatic
+ # - :manual
+ # - :disabled
+ # Reference: https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L49-L54
+ property :startup_type, [Symbol], equal_to: [:automatic, :manual, :disabled], default: :automatic, coerce: proc { |x|
+ if x.is_a?(Integer)
+ ALLOWED_START_TYPES.invert.fetch(x) do
+ Chef::Log.warn("Unsupported startup_type #{x}, falling back to :automatic")
+ :automatic
+ end
+ elsif x.is_a?(String)
+ x.to_sym
+ else
+ x
+ end
+ }
+
+ # This only applies if startup_type is :automatic
+ # 1 == delayed start is enabled
+ # 0 == NO delayed start
+ property :delayed_start, [TrueClass, FalseClass], default: false, coerce: proc { |x|
+ if x.is_a?(Integer)
+ x == 0 ? false : true
+ else
+ x
+ end
+ }
+
+ # https://github.com/djberg96/win32-service/blob/ffi/lib/win32/windows/constants.rb#L43-L47
+ property :error_control, Integer, default: SERVICE_ERROR_NORMAL
+
+ # The fully qualified path to the service binary file. The path can also
+ # include arguments for an auto-start service.
+ #
+ # This is required for :create and :configure actions -- intentionally
+ # not setting required: true here to support other actions
+ property :binary_path_name, String
+
+ # The names of the load ordering group of which this service is a member.
+ # Specify nil or an empty string if the service does not belong to a group.
+ property :load_order_group, String
+
+ # A pointer to a double null-terminated array of null-separated names of
+ # services or load ordering groups that the system must start before this
+ # service. Specify nil or an empty string if the service has no
+ # dependencies. Dependency on a group means that this service can run if
+ # at least one member of the group is running after an attempt to start
+ # all members of the group.
+ property :dependencies, [String, Array]
+
+ property :description, String
+
+ property :run_as_user, String, default: "LocalSystem"
+ property :run_as_password, String, default: ""
end
end
end
diff --git a/lib/chef/resource/windows_task.rb b/lib/chef/resource/windows_task.rb
index f9c0599c49..1b2c331e36 100644
--- a/lib/chef/resource/windows_task.rb
+++ b/lib/chef/resource/windows_task.rb
@@ -20,21 +20,18 @@ require "chef/resource"
class Chef
class Resource
+ # Use the windows_task resource to create, delete or run a Windows scheduled task. Requires Windows Server 2008
+ # or later due to API usage.
+ # @since 13.0
class WindowsTask < Chef::Resource
+ resource_name :windows_task
provides :windows_task, os: "windows"
allowed_actions :create, :delete, :run, :end, :enable, :disable
default_action :create
- def initialize(name, run_context = nil)
- super
- @resource_name = :windows_task
- @task_name = name
- @action = :create
- end
-
- property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/]
+ property :task_name, String, regex: [/\A[^\/\:\*\?\<\>\|]+\z/], name_property: true
property :command, String
property :cwd, String
property :user, String, default: "SYSTEM"
@@ -44,21 +41,22 @@ class Chef
property :interactive_enabled, [TrueClass, FalseClass], default: false
property :frequency_modifier, [Integer, String], default: 1
property :frequency, equal_to: [:minute,
- :hourly,
- :daily,
- :weekly,
- :monthly,
- :once,
- :on_logon,
- :onstart,
- :on_idle], default: :hourly
+ :hourly,
+ :daily,
+ :weekly,
+ :monthly,
+ :once,
+ :on_logon,
+ :onstart,
+ :on_idle,
+ :none], default: :hourly
property :start_day, String
property :start_time, String
property :day, [String, Integer]
property :months, String
property :idle_time, Integer
- property :random_delay, String
- property :execution_time_limit, String
+ property :random_delay, [String, Integer]
+ property :execution_time_limit, [String, Integer], default: "PT72H" # 72 hours in ISO8601 duration format
attr_accessor :exists, :status, :enabled
@@ -70,59 +68,71 @@ class Chef
end
if execution_time_limit
- raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as a String e.g. '60'." if execution_time_limit.to_i == 0
- duration = sec_to_dur(execution_time_limit)
- execution_time_limit(duration)
- else
- # schtask sets execution_time_limit as PT72H by default
- # We are setting the default value here so that we can do idempotency check later
- # Note: We can't use `default` in the property
- # because it will raise error for Invalid values passed as "PT72H" is not in seconds
- execution_time_limit("PT72H")
+ unless execution_time_limit == "PT72H" # don't double convert an ISO8601 format duration
+ raise ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(execution_time_limit)
+ duration = sec_to_dur(execution_time_limit)
+ execution_time_limit(duration)
+ end
end
- validate_start_time(start_time) if frequency == :once
+ validate_start_time(start_time, frequency)
validate_start_day(start_day, frequency) if start_day
validate_user_and_password(user, password)
validate_interactive_setting(interactive_enabled, password)
validate_create_frequency_modifier(frequency, frequency_modifier)
validate_create_day(day, frequency) if day
validate_create_months(months, frequency) if months
- validate_idle_time(idle_time, frequency) if idle_time
+ validate_idle_time(idle_time, frequency)
end
private
+ # Validate the passed value is numeric values only if it is a string
+ def numeric_value_in_string?(val)
+ return true if Integer(val)
+ rescue ArgumentError
+ false
+ end
+
def validate_random_delay(random_delay, frequency)
- if [:once, :on_logon, :onstart, :on_idle].include? frequency
+ if [:once, :on_logon, :onstart, :on_idle, :none].include? frequency
raise ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly"
end
- raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as a String e.g. '60'." if random_delay.to_i == 0
+ raise ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60')." unless numeric_value_in_string?(random_delay)
end
+ # @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~f
def validate_start_day(start_day, frequency)
- if [:once, :on_logon, :onstart, :on_idle].include? frequency
+ if [:once, :on_logon, :onstart, :on_idle, :none].include? frequency
raise ArgumentError, "`start_day` property is not supported with frequency: #{frequency}"
end
+
+ # make sure the start_day is in MM/DD/YYYY format: http://rubular.com/r/cgjHemtWl5
+ raise ArgumentError, "`start_day` property must be in the MM/DD/YYYY format." unless /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d$/ =~ start_day
end
- def validate_start_time(start_time)
- raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" unless start_time
+ # @todo when we drop ruby 2.3 support this should be converted to .match?() instead of =~
+ def validate_start_time(start_time, frequency)
+ if start_time
+ raise ArgumentError, "`start_time` property is not supported with `frequency :none`" if frequency == :none
+ raise ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20)." unless /^[0-2][0-9]:[0-5][0-9]$/ =~ start_time
+ else
+ raise ArgumentError, "`start_time` needs to be provided with `frequency :once`" if frequency == :once
+ end
end
SYSTEM_USERS = ['NT AUTHORITY\SYSTEM', "SYSTEM", 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', "USERS"].freeze
def validate_user_and_password(user, password)
- if user && use_password?(user)
- if password.nil?
- raise ArgumentError, "Can't specify a non-system user without a password!"
- end
+ if password_required?(user) && password.nil?
+ raise ArgumentError, %q{Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: 'NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', 'USERS'}
end
end
- def use_password?(user)
- @use_password ||= !SYSTEM_USERS.include?(user.upcase)
+ def password_required?(user)
+ return false if user.nil?
+ @password_required ||= !SYSTEM_USERS.include?(user.upcase)
end
def validate_interactive_setting(interactive_enabled, password)
@@ -132,29 +142,29 @@ class Chef
end
def validate_create_frequency_modifier(frequency, frequency_modifier)
- # Currently is handled in create action 'frequency_modifier_allowed' line. Does not allow for frequency_modifier for once,onstart,onlogon,onidle
+ # Currently is handled in create action 'frequency_modifier_allowed' line. Does not allow for frequency_modifier for once,onstart,onlogon,onidle,none
# Note that 'OnEvent' is not a supported frequency.
unless frequency.nil? || frequency_modifier.nil?
case frequency
when :minute
unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 1439
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :minute frequency are 1 - 1439."
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :minute frequency are 1 - 1439."
end
when :hourly
unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 23
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :hourly frequency are 1 - 23."
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :hourly frequency are 1 - 23."
end
when :daily
unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 365
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :daily frequency are 1 - 365."
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :daily frequency are 1 - 365."
end
when :weekly
unless frequency_modifier.to_i > 0 && frequency_modifier.to_i <= 52
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :weekly frequency are 1 - 52."
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :weekly frequency are 1 - 52."
end
when :monthly
unless ("1".."12").to_a.push("FIRST", "SECOND", "THIRD", "FOURTH", "LAST", "LASTDAY").include?(frequency_modifier.to_s.upcase)
- raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'."
+ raise ArgumentError, "frequency_modifier value #{frequency_modifier} is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'."
end
end
end
@@ -162,74 +172,48 @@ class Chef
def validate_create_day(day, frequency)
unless [:weekly, :monthly].include?(frequency)
- raise "day attribute is only valid for tasks that run monthly or weekly"
+ raise "day property is only valid for tasks that run monthly or weekly"
end
if day.is_a?(String) && day.to_i.to_s != day
days = day.split(",")
days.each do |d|
unless ["mon", "tue", "wed", "thu", "fri", "sat", "sun", "*"].include?(d.strip.downcase)
- raise "day attribute invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma."
+ raise ArgumentError, "day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma."
end
end
end
end
def validate_create_months(months, frequency)
- unless [:monthly].include?(frequency)
- raise "months attribute is only valid for tasks that run monthly"
- end
+ raise ArgumentError, "months property is only valid for tasks that run monthly" unless frequency == :monthly
if months.is_a? String
months.split(",").each do |month|
unless ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", "*"].include?(month.strip.upcase)
- raise "months attribute invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma."
+ raise ArgumentError, "months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma."
end
end
end
end
def validate_idle_time(idle_time, frequency)
- unless [:on_idle].include?(frequency)
- raise "idle_time attribute is only valid for tasks that run on_idle"
+ if !idle_time.nil? && frequency != :on_idle
+ raise ArgumentError, "idle_time property is only valid for tasks that run on_idle"
end
-
- unless idle_time.to_i > 0 && idle_time.to_i <= 999
- raise "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
+ if idle_time.nil? && frequency == :on_idle
+ raise ArgumentError, "idle_time value should be set for :on_idle frequency."
+ end
+ unless idle_time.nil? || idle_time > 0 && idle_time <= 999
+ raise ArgumentError, "idle_time value #{idle_time} is invalid. Valid values for :on_idle frequency are 1 - 999."
end
end
- # Convert the number of seconds to an ISO8601 duration format
- # @see http://tools.ietf.org/html/rfc2445#section-4.3.6
- # @param [Integer] seconds The amount of seconds for this duration
+ # Converts the number of seconds to an ISO8601 duration format and returns it.
+ # Ref : https://github.com/arnau/ISO8601/blob/master/lib/iso8601/duration.rb#L18-L23
+ # e.g.
+ # ISO8601::Duration.new(65707200)
+ # returns 'P65707200S'
def sec_to_dur(seconds)
- seconds = seconds.to_i
- return if seconds == 0
- iso_str = "P"
- if seconds > 604_800 # more than a week
- weeks = seconds / 604_800
- seconds -= (604_800 * weeks)
- iso_str << "#{weeks}W"
- end
- if seconds > 86_400 # more than a day
- days = seconds / 86_400
- seconds -= (86_400 * days)
- iso_str << "#{days}D"
- end
- if seconds > 0
- iso_str << "T"
- if seconds > 3600 # more than an hour
- hours = seconds / 3600
- seconds -= (3600 * hours)
- iso_str << "#{hours}H"
- end
- if seconds > 60 # more than a minute
- minutes = seconds / 60
- seconds -= (60 * minutes)
- iso_str << "#{minutes}M"
- end
- iso_str << "#{seconds}S"
- end
-
- iso_str
+ ISO8601::Duration.new(seconds.to_i).to_s
end
end
diff --git a/lib/chef/resource/yum_repository.rb b/lib/chef/resource/yum_repository.rb
index f59ad56d16..7c30bc5457 100644
--- a/lib/chef/resource/yum_repository.rb
+++ b/lib/chef/resource/yum_repository.rb
@@ -1,6 +1,6 @@
#
# Author:: Thom May (<thom@chef.io>)
-# Copyright:: Copyright (c) 2016 Chef Software, Inc.
+# Copyright:: Copyright (c) 2016-2017 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,52 +20,59 @@ require "chef/resource"
class Chef
class Resource
+ # Use the yum_repository resource to manage a Yum repository configuration file located at /etc/yum.repos.d/repositoryid.repo
+ # on the local machine. This configuration file specifies which repositories to reference, how to handle cached data, etc.
+ #
+ # @since 12.14
class YumRepository < Chef::Resource
resource_name :yum_repository
provides :yum_repository
- # http://linux.die.net/man/5/yum.conf
- property :baseurl, [String, Array], regex: /.*/
- property :cost, String, regex: /^\d+$/
+ # http://linux.die.net/man/5/yum.conf as well as
+ # http://dnf.readthedocs.io/en/latest/conf_ref.html
+ property :baseurl, [String, Array]
property :clean_headers, [TrueClass, FalseClass], default: false # deprecated
property :clean_metadata, [TrueClass, FalseClass], default: true
- property :description, String, regex: /.*/, default: "Yum Repository"
+ property :cost, String, regex: /^\d+$/
+ property :description, String, default: "Yum Repository"
property :enabled, [TrueClass, FalseClass], default: true
property :enablegroups, [TrueClass, FalseClass]
- property :exclude, String, regex: /.*/
+ property :exclude, String
property :failovermethod, String, equal_to: %w{priority roundrobin}
property :fastestmirror_enabled, [TrueClass, FalseClass]
property :gpgcheck, [TrueClass, FalseClass], default: true
- property :gpgkey, [String, Array], regex: /.*/
+ property :gpgkey, [String, Array]
property :http_caching, String, equal_to: %w{packages all none}
- property :include_config, String, regex: /.*/
- property :includepkgs, String, regex: /.*/
+ property :include_config, String
+ property :includepkgs, String
property :keepalive, [TrueClass, FalseClass]
property :make_cache, [TrueClass, FalseClass], default: true
property :max_retries, [String, Integer]
property :metadata_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/, /never/]
- property :mirrorexpire, String, regex: /.*/
- property :mirrorlist, String, regex: /.*/
+ property :metalink, String
property :mirror_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/]
+ property :mirrorexpire, String
property :mirrorlist_expire, String, regex: [/^\d+$/, /^\d+[mhd]$/]
+ property :mirrorlist, String
property :mode, default: "0644"
- property :priority, String, regex: /^(\d?[0-9]|[0-9][0-9])$/
- property :proxy, String, regex: /.*/
- property :proxy_username, String, regex: /.*/
- property :proxy_password, String, regex: /.*/
- property :username, String, regex: /.*/
- property :password, String, regex: /.*/
+ property :options, Hash
+ property :password, String
+ property :priority, String, regex: /^(\d?[1-9]|[0-9][0-9])$/
+ property :proxy_password, String
+ property :proxy_username, String
+ property :proxy, String
property :repo_gpgcheck, [TrueClass, FalseClass]
property :report_instanceid, [TrueClass, FalseClass]
- property :repositoryid, String, regex: /.*/, name_property: true
+ property :repositoryid, String, name_property: true
property :skip_if_unavailable, [TrueClass, FalseClass]
- property :source, String, regex: /.*/
- property :sslcacert, String, regex: /.*/
- property :sslclientcert, String, regex: /.*/
- property :sslclientkey, String, regex: /.*/
+ property :source, String
+ property :sslcacert, String
+ property :sslclientcert, String
+ property :sslclientkey, String
property :sslverify, [TrueClass, FalseClass]
+ property :throttle, [String, Integer]
property :timeout, String, regex: /^\d+$/
- property :options, Hash
+ property :username, String
default_action :create
allowed_actions :create, :remove, :makecache, :add, :delete
diff --git a/lib/chef/resource/zypper_package.rb b/lib/chef/resource/zypper_package.rb
index 6c6e308159..f412d59988 100644
--- a/lib/chef/resource/zypper_package.rb
+++ b/lib/chef/resource/zypper_package.rb
@@ -20,11 +20,14 @@ require "chef/resource/package"
class Chef
class Resource
+ # Use the zypper_package resource to install, upgrade, and remove packages with Zypper for the SUSE Enterprise and
+ # OpenSUSE platforms.
class ZypperPackage < Chef::Resource::Package
resource_name :zypper_package
provides :package, platform_family: "suse"
property :gpg_check, [ TrueClass, FalseClass ], default: lazy { Chef::Config[:zypper_check_gpg] }
+ property :allow_downgrade, [ true, false ], default: false
end
end
end
diff --git a/lib/chef/resource/zypper_repository.rb b/lib/chef/resource/zypper_repository.rb
index 69a96b42cf..72e0074b2a 100644
--- a/lib/chef/resource/zypper_repository.rb
+++ b/lib/chef/resource/zypper_repository.rb
@@ -20,6 +20,11 @@ require "chef/resource"
class Chef
class Resource
+ # The zypper_repository resource allows for the creation of Zypper package repositories on SUSE Enterprise Linux and
+ # openSUSE systems. This resource maintains full compatibility with the zypper_repository resource in the existing
+ # zypper cookbook.
+ #
+ # @since 13.3
class ZypperRepository < Chef::Resource
resource_name :zypper_repository
provides :zypper_repo
@@ -38,7 +43,8 @@ class Chef
property :keeppackages, [true, false], default: false
property :mode, default: "0644"
property :refresh_cache, [true, false], default: true
- property :source, String, regex: /.*/
+ property :source, String
+ property :cookbook, String
property :gpgautoimportkeys, [true, false], default: true
default_action :create
diff --git a/lib/chef/resource_reporter.rb b/lib/chef/resource_reporter.rb
index afc8500a2a..53e7ea9e30 100644
--- a/lib/chef/resource_reporter.rb
+++ b/lib/chef/resource_reporter.rb
@@ -3,7 +3,7 @@
# Author:: Prajakta Purohit (prajakta@chef.io>)
# Auther:: Tyler Cloke (<tyler@opscode.com>)
#
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -94,7 +94,6 @@ class Chef
attr_reader :updated_resources
attr_reader :status
attr_reader :exception
- attr_reader :run_id
attr_reader :error_descriptions
PROTOCOL_VERSION = "0.1.0"
diff --git a/lib/chef/resources.rb b/lib/chef/resources.rb
index 54d21fd53c..9fee978432 100644
--- a/lib/chef/resources.rb
+++ b/lib/chef/resources.rb
@@ -28,15 +28,12 @@ require "chef/resource/chef_gem"
require "chef/resource/chocolatey_package"
require "chef/resource/cron"
require "chef/resource/csh"
-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/env"
-require "chef/resource/erl_call"
require "chef/resource/execute"
require "chef/resource/file"
require "chef/resource/freebsd_package"
@@ -56,6 +53,9 @@ require "chef/resource/mdadm"
require "chef/resource/mount"
require "chef/resource/ohai"
require "chef/resource/openbsd_package"
+require "chef/resource/openssl_dhparam"
+require "chef/resource/openssl_rsa_private_key"
+require "chef/resource/openssl_rsa_public_key"
require "chef/resource/package"
require "chef/resource/pacman_package"
require "chef/resource/paludis_package"
@@ -81,7 +81,6 @@ require "chef/resource/windows_service"
require "chef/resource/subversion"
require "chef/resource/smartos_package"
require "chef/resource/template"
-require "chef/resource/timestamped_deploy"
require "chef/resource/user"
require "chef/resource/user/aix_user"
require "chef/resource/user/dscl_user"
diff --git a/lib/chef/role.rb b/lib/chef/role.rb
index c22c77b70d..ad01e9fa26 100644
--- a/lib/chef/role.rb
+++ b/lib/chef/role.rb
@@ -2,7 +2,7 @@
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: Nuo Yan (<nuo@chef.io>)
# Author:: Christopher Brown (<cb@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,8 +33,6 @@ class Chef
include Chef::Mixin::FromFile
include Chef::Mixin::ParamsValidate
- attr_accessor :chef_server_rest
-
# Create a new Chef::Role object.
def initialize(chef_server_rest: nil)
@name = ""
diff --git a/lib/chef/run_context.rb b/lib/chef/run_context.rb
index fc32ab3eeb..b2eee0406e 100644
--- a/lib/chef/run_context.rb
+++ b/lib/chef/run_context.rb
@@ -29,7 +29,6 @@ require "forwardable"
class Chef
- # == Chef::RunContext
# Value object that loads and tracks the context of a Chef run
class RunContext
#
@@ -312,7 +311,7 @@ class Chef
#
# @param recipe_names [Array[String]] The recipe name (e.g 'my_cookbook' or
# 'my_cookbook::my_resource').
- # @param current_cookbook The cookbook we are currently running in.
+ # @param current_cookbook [String] The cookbook we are currently running in.
#
# @return A truthy value if the load occurred; `false` if already loaded.
#
@@ -556,11 +555,18 @@ ERROR_MESSAGE
@reboot_info = reboot_info
end
+ #
+ # Cancels a pending reboot
+ #
def cancel_reboot
Chef::Log.info "Changing reboot status from #{reboot_info.inspect} to {}"
@reboot_info = {}
end
+ #
+ # Checks to see if a reboot has been requested
+ # @return [Boolean]
+ #
def reboot_requested?
reboot_info.size > 0
end
diff --git a/lib/chef/search/query.rb b/lib/chef/search/query.rb
index a2663d111d..b7b15765bb 100644
--- a/lib/chef/search/query.rb
+++ b/lib/chef/search/query.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,7 +27,6 @@ class Chef
class Search
class Query
- attr_accessor :rest
attr_reader :config
def initialize(url = nil, config: Chef::Config)
diff --git a/lib/chef/server_api.rb b/lib/chef/server_api.rb
index 2bdc5d9fe8..c501544954 100644
--- a/lib/chef/server_api.rb
+++ b/lib/chef/server_api.rb
@@ -31,6 +31,7 @@ class Chef
def initialize(url = Chef::Config[:chef_server_url], options = {})
options[:client_name] ||= Chef::Config[:node_name]
+ options[:raw_key] ||= Chef::Config[:client_key_contents]
options[:signing_key_filename] ||= Chef::Config[:client_key] unless options[:raw_key]
options[:signing_key_filename] = nil if chef_zero_uri?(url)
options[:inflate_json_class] = false
diff --git a/lib/chef/shell.rb b/lib/chef/shell.rb
index 40bdf01762..88d26e78fc 100644
--- a/lib/chef/shell.rb
+++ b/lib/chef/shell.rb
@@ -41,7 +41,6 @@ module Shell
LEADERS[Chef::Node] = ":attributes"
class << self
- attr_accessor :client_type
attr_accessor :options
attr_accessor :env
attr_writer :editor
diff --git a/lib/chef/shell/model_wrapper.rb b/lib/chef/shell/model_wrapper.rb
index 8c3e456a9b..4394caa395 100644
--- a/lib/chef/shell/model_wrapper.rb
+++ b/lib/chef/shell/model_wrapper.rb
@@ -17,7 +17,7 @@
#
require "chef/mixin/convert_to_class_name"
-require "chef/mixin/language"
+require "chef/dsl/data_query"
module Shell
class ModelWrapper
diff --git a/lib/chef/shell/shell_session.rb b/lib/chef/shell/shell_session.rb
index dfed5372c1..ce2e457461 100644
--- a/lib/chef/shell/shell_session.rb
+++ b/lib/chef/shell/shell_session.rb
@@ -2,7 +2,7 @@
# Author:: Daniel DeLeo (<dan@kallistec.com>)
# Author:: Tim Hinderliter (<tim@chef.io>)
# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -38,7 +38,7 @@ module Shell
@session_type
end
- attr_accessor :node, :compile, :recipe, :run_context, :json_configuration
+ attr_accessor :node, :compile, :recipe, :json_configuration
attr_reader :node_attributes, :client
def initialize
@node_built = false
@@ -73,6 +73,7 @@ module Shell
run_context.resource_collection
end
+ attr_writer :run_context
def run_context
@run_context ||= rebuild_context
end
diff --git a/lib/chef/util/dsc/lcm_output_parser.rb b/lib/chef/util/dsc/lcm_output_parser.rb
index 9473ca8a86..f19f637b6d 100644
--- a/lib/chef/util/dsc/lcm_output_parser.rb
+++ b/lib/chef/util/dsc/lcm_output_parser.rb
@@ -28,7 +28,7 @@ class Chef
# Parses the output from LCM and returns a list of Chef::Util::DSC::ResourceInfo objects
# that describe how the resources affected the system
#
- # Example:
+ # Example for WhatIfParser:
# parse <<-EOF
# What if: [Machine]: LCM: [Start Set ]
# What if: [Machine]: LCM: [Start Resource ] [[File]FileToNotBeThere]
@@ -53,7 +53,62 @@ class Chef
# )
# ]
#
- def self.parse(lcm_output)
+ # Example for TestDSCParser:
+ # parse <<-EOF
+ # InDesiredState : False
+ # ResourcesInDesiredState :
+ # ResourcesNotInDesiredState: {[Environment]texteditor}
+ # ReturnValue : 0
+ # PSComputerName : .
+ # EOF
+ #
+ # would return
+ #
+ # [
+ # Chef::Util::DSC::ResourceInfo.new(
+ # '{[Environment]texteditor}',
+ # true,
+ # [
+ # ]
+ # )
+ # ]
+ #
+
+ def self.parse(lcm_output, test_dsc_configuration)
+ test_dsc_configuration ? test_dsc_parser(lcm_output) : what_if_parser(lcm_output)
+ end
+
+ def self.test_dsc_parser(lcm_output)
+ lcm_output ||= ""
+ current_resource = Hash.new
+
+ resources = []
+ lcm_output.lines.each do |line|
+ op_action , op_value = line.strip.split(":")
+ op_action&.strip!
+ case op_action
+ when "InDesiredState"
+ current_resource[:skipped] = op_value.strip == "True" ? true : false
+ when "ResourcesInDesiredState"
+ current_resource[:name] = op_value.strip if op_value
+ when "ResourcesNotInDesiredState"
+ current_resource[:name] = op_value.strip if op_value
+ when "ReturnValue"
+ current_resource[:context] = nil
+ end
+ end
+ if current_resource[:name]
+ resources.push(current_resource)
+ end
+
+ if resources.length > 0
+ build_resource_info(resources)
+ else
+ raise Chef::Exceptions::LCMParser, "Could not parse:\n#{lcm_output}"
+ end
+ end
+
+ def self.what_if_parser(lcm_output)
lcm_output ||= ""
current_resource = Hash.new
diff --git a/lib/chef/util/dsc/local_configuration_manager.rb b/lib/chef/util/dsc/local_configuration_manager.rb
index 1f154b1c71..07109f7f92 100644
--- a/lib/chef/util/dsc/local_configuration_manager.rb
+++ b/lib/chef/util/dsc/local_configuration_manager.rb
@@ -29,7 +29,7 @@ class Chef::Util::DSC
def test_configuration(configuration_document, shellout_flags)
status = run_configuration_cmdlet(configuration_document, false, shellout_flags)
- log_what_if_exception(status.stderr) unless status.succeeded?
+ log_dsc_exception(status.stderr) unless status.succeeded?
configuration_update_required?(status.return_value)
end
@@ -77,7 +77,7 @@ class Chef::Util::DSC
ps4_base_command
else
if ps_version_gte_5?
- "#{common_command_prefix} Test-DscConfiguration -path #{@configuration_path}"
+ "#{common_command_prefix} Test-DscConfiguration -path #{@configuration_path} | format-list"
else
ps4_base_command + " -whatif; if (! $?) { exit 1 }"
end
@@ -88,31 +88,31 @@ class Chef::Util::DSC
Chef::Platform.supported_powershell_version?(@node, 5)
end
- def log_what_if_exception(what_if_exception_output)
- if whatif_not_supported?(what_if_exception_output)
+ def log_dsc_exception(dsc_exception_output)
+ if whatif_not_supported?(dsc_exception_output)
# LCM returns an error if any of the resources do not support the opptional What-If
Chef::Log.warn("Received error while testing configuration due to resource not supporting 'WhatIf'")
- elsif dsc_module_import_failure?(what_if_exception_output)
- Chef::Log.warn("Received error while testing configuration due to a module for an imported resource possibly not being fully installed:\n#{what_if_exception_output.gsub(/\s+/, ' ')}")
+ elsif dsc_module_import_failure?(dsc_exception_output)
+ Chef::Log.warn("Received error while testing configuration due to a module for an imported resource possibly not being fully installed:\n#{dsc_exception_output.gsub(/\s+/, ' ')}")
else
- Chef::Log.warn("Received error while testing configuration:\n#{what_if_exception_output.gsub(/\s+/, ' ')}")
+ Chef::Log.warn("Received error while testing configuration:\n#{dsc_exception_output.gsub(/\s+/, ' ')}")
end
end
- def whatif_not_supported?(what_if_exception_output)
- !! (what_if_exception_output.gsub(/[\r\n]+/, "").gsub(/\s+/, " ") =~ /A parameter cannot be found that matches parameter name 'Whatif'/i)
+ def whatif_not_supported?(dsc_exception_output)
+ !! (dsc_exception_output.gsub(/[\r\n]+/, "").gsub(/\s+/, " ") =~ /A parameter cannot be found that matches parameter name 'Whatif'/i)
end
- def dsc_module_import_failure?(what_if_output)
- !! (what_if_output =~ /\sCimException/ &&
- what_if_output =~ /ProviderOperationExecutionFailure/ &&
- what_if_output =~ /\smodule\s+is\s+installed/)
+ def dsc_module_import_failure?(command_output)
+ !! (command_output =~ /\sCimException/ &&
+ command_output =~ /ProviderOperationExecutionFailure/ &&
+ command_output =~ /\smodule\s+is\s+installed/)
end
- def configuration_update_required?(what_if_output)
- Chef::Log.debug("DSC: DSC returned the following '-whatif' output from test operation:\n#{what_if_output}")
+ def configuration_update_required?(command_output)
+ Chef::Log.debug("DSC: DSC returned the following '-whatif' output from test operation:\n#{command_output}")
begin
- Parser.parse(what_if_output)
+ Parser.parse(command_output, ps_version_gte_5?)
rescue Chef::Exceptions::LCMParser => e
Chef::Log.warn("Could not parse LCM output: #{e}")
[Chef::Util::DSC::ResourceInfo.new("Unknown DSC Resources", true, ["Unknown changes because LCM output was not parsable."])]
diff --git a/lib/chef/util/selinux.rb b/lib/chef/util/selinux.rb
index 0ff76c6407..8b4c38754c 100644
--- a/lib/chef/util/selinux.rb
+++ b/lib/chef/util/selinux.rb
@@ -48,10 +48,11 @@ class Chef
def restore_security_context(file_path, recursive = false)
if restorecon_path
- restorecon_command = recursive ? "#{restorecon_path} -R -r" : "#{restorecon_path} -R"
- restorecon_command += " \"#{file_path}\""
- Chef::Log.debug("Restoring selinux security content with #{restorecon_command}")
- shell_out!(restorecon_command)
+ restorecon_flags = [ "-R" ]
+ restorecon_flags << "-r" if recursive
+ restorecon_flags << file_path
+ Chef::Log.debug("Restoring selinux security content with #{restorecon_path}")
+ shell_out_compact!(restorecon_path, restorecon_flags)
else
Chef::Log.warn "Can not find 'restorecon' on the system. Skipping selinux security context restore."
end
diff --git a/lib/chef/util/windows/logon_session.rb b/lib/chef/util/windows/logon_session.rb
index ef80b113b1..afe58ae4f9 100644
--- a/lib/chef/util/windows/logon_session.rb
+++ b/lib/chef/util/windows/logon_session.rb
@@ -25,7 +25,7 @@ class Chef
class LogonSession
include Chef::Mixin::WideString
- def initialize(username, password, domain = nil)
+ def initialize(username, password, domain = nil, authentication = :remote)
if username.nil? || password.nil?
raise ArgumentError, "The logon session must be initialize with non-nil user name and password parameters"
end
@@ -33,6 +33,7 @@ class Chef
@original_username = username
@original_password = password
@original_domain = domain
+ @authentication = authentication
@token = FFI::Buffer.new(:pointer)
@session_opened = false
@impersonating = false
@@ -47,7 +48,8 @@ class Chef
password = wstring(original_password)
domain = wstring(original_domain)
- status = Chef::ReservedNames::Win32::API::Security.LogonUserW(username, domain, password, Chef::ReservedNames::Win32::API::Security::LOGON32_LOGON_NEW_CREDENTIALS, Chef::ReservedNames::Win32::API::Security::LOGON32_PROVIDER_DEFAULT, token)
+ logon_type = (authentication == :local) ? (Chef::ReservedNames::Win32::API::Security::LOGON32_LOGON_NETWORK) : (Chef::ReservedNames::Win32::API::Security::LOGON32_LOGON_NEW_CREDENTIALS)
+ status = Chef::ReservedNames::Win32::API::Security.LogonUserW(username, domain, password, logon_type, Chef::ReservedNames::Win32::API::Security::LOGON32_PROVIDER_DEFAULT, token)
if !status
last_error = FFI::LastError.error
@@ -110,6 +112,7 @@ class Chef
attr_reader :original_username
attr_reader :original_password
attr_reader :original_domain
+ attr_reader :authentication
attr_reader :token
attr_reader :session_opened
diff --git a/lib/chef/util/windows/volume.rb b/lib/chef/util/windows/volume.rb
index dc9c0ca1d0..358a3f4bb8 100644
--- a/lib/chef/util/windows/volume.rb
+++ b/lib/chef/util/windows/volume.rb
@@ -46,8 +46,4 @@ class Chef::Util::Windows::Volume < Chef::Util::Windows
rescue Chef::Exceptions::Win32APIError => e
raise ArgumentError, e
end
-
- def mount_point
- @mount_point
- end
end
diff --git a/lib/chef/version.rb b/lib/chef/version.rb
index e4dc4a75d1..3ece62f847 100644
--- a/lib/chef/version.rb
+++ b/lib/chef/version.rb
@@ -23,7 +23,7 @@ require "chef/version_string"
class Chef
CHEF_ROOT = File.expand_path("../..", __FILE__)
- VERSION = Chef::VersionString.new("13.4.30")
+ VERSION = Chef::VersionString.new("14.0.52")
end
#
diff --git a/lib/chef/version/platform.rb b/lib/chef/version/platform.rb
index 07b1a17b11..6d8f4192fe 100644
--- a/lib/chef/version/platform.rb
+++ b/lib/chef/version/platform.rb
@@ -16,6 +16,24 @@
require "chef/version_class"
+# NOTE: this is fairly badly broken for its purpose and should not be used
+# unless it gets fixed.
+
+# this strictly wants x, x.y, or x.y.z version constraints in the target and
+# will fail hard if it does not match. the semantics that we need here is that
+# it must always do the best job that it can do and consume as much of the
+# offered version as it can. since we accept arbitrarily parsed strings into
+# node[:platform_version] out of dozens or potentially hundreds of operating
+# systems this parsing code needs to be fixed to never raise. the Gem::Version
+# class is a better model, and in fact it might be a substantially better approach
+# to base this class on Gem::Version and then do pre-mangling of things like windows
+# version strings via e.g. `.gsub(/R/, '.')`. the raising behavior of this parser
+# however, breaks the ProviderResolver in a not just buggy but a "completely unfit
+# for purpose" way.
+#
+# TL;DR: MUST follow the second part of "Be conservative in what you send,
+# be liberal in what you accept"
+#
class Chef
class Version
class Platform < Chef::Version
diff --git a/lib/chef/version_constraint/platform.rb b/lib/chef/version_constraint/platform.rb
index 29f4678bb5..e39da194c6 100644
--- a/lib/chef/version_constraint/platform.rb
+++ b/lib/chef/version_constraint/platform.rb
@@ -16,6 +16,8 @@
require "chef/version_constraint"
require "chef/version/platform"
+# NOTE: this is fairly badly broken for its purpose and should not be used
+# unless it gets fixed. see chef/version/platform.
class Chef
class VersionConstraint
class Platform < Chef::VersionConstraint
diff --git a/lib/chef/win32/api/security.rb b/lib/chef/win32/api/security.rb
index a6f79f5d7d..6620f321aa 100644
--- a/lib/chef/win32/api/security.rb
+++ b/lib/chef/win32/api/security.rb
@@ -303,6 +303,17 @@ class Chef
:SecurityDelegation,
]
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/bb530718%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+ ELEVATION_TYPE = enum :ELEVATION_TYPE, [
+ :TokenElevationTypeDefault, 1,
+ :TokenElevationTypeFull,
+ :TokenElevationTypeLimited
+ ]
+
+ class TOKEN_ELEVATION_TYPE < FFI::Struct
+ layout :ElevationType, :ELEVATION_TYPE
+ end
+
# SECURITY_DESCRIPTOR is an opaque structure whose contents can vary. Pass the
# pointer around and free it with LocalFree.
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa379561(v=vs.85).aspx
diff --git a/lib/chef/win32/registry.rb b/lib/chef/win32/registry.rb
index 6f1eb9ff12..4a1dbe3eac 100644
--- a/lib/chef/win32/registry.rb
+++ b/lib/chef/win32/registry.rb
@@ -2,7 +2,7 @@
# Author:: Prajakta Purohit (<prajakta@chef.io>)
# Author:: Lamont Granquist (<lamont@chef.io>)
#
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ class Chef
extend Chef::Mixin::WideString
attr_accessor :run_context
- attr_accessor :architecture
+ attr_reader :architecture
def initialize(run_context = nil, user_architecture = :machine)
@run_context = run_context
diff --git a/lib/chef/win32/security.rb b/lib/chef/win32/security.rb
index c7d3f55a40..63b626b1d7 100644
--- a/lib/chef/win32/security.rb
+++ b/lib/chef/win32/security.rb
@@ -341,6 +341,22 @@ class Chef
SID.new(group_result[:PrimaryGroup], group_result_storage)
end
+ def self.get_token_information_elevation_type(token)
+ token_result_size = FFI::MemoryPointer.new(:ulong)
+ if GetTokenInformation(token.handle.handle, :TokenElevationType, nil, 0, token_result_size)
+ raise "Expected ERROR_INSUFFICIENT_BUFFER from GetTokenInformation, and got no error!"
+ elsif FFI::LastError.error != ERROR_INSUFFICIENT_BUFFER
+ Chef::ReservedNames::Win32::Error.raise!
+ end
+ info_ptr = FFI::MemoryPointer.new(:pointer)
+ token_info_pointer = TOKEN_ELEVATION_TYPE.new info_ptr
+ token_info_length = 4
+ unless GetTokenInformation(token.handle.handle, :TokenElevationType, token_info_pointer, token_info_length, token_result_size)
+ Chef::ReservedNames::Win32::Error.raise!
+ end
+ token_info_pointer[:ElevationType]
+ end
+
def self.initialize_acl(acl_size)
acl = FFI::MemoryPointer.new acl_size
unless InitializeAcl(acl, acl_size, ACL_REVISION)
@@ -632,7 +648,19 @@ class Chef
true
else
- process_token = open_current_process_token(TOKEN_READ)
+ # a regular user doesn't have privileges to call Chef::ReservedNames::Win32::Security.OpenProcessToken
+ # hence we return false if the open_current_process_token fails with `Access is denied.` error message.
+ begin
+ process_token = open_current_process_token(TOKEN_READ)
+ rescue Exception => run_error
+ return false if run_error.message =~ /Access is denied/
+ Chef::ReservedNames::Win32::Error.raise!
+ end
+
+ # display token elevation details
+ token_elevation_type = get_token_information_elevation_type(process_token)
+ Chef::Log.debug("Token Elevation Type: #{token_elevation_type}")
+
elevation_result = FFI::Buffer.new(:ulong)
elevation_result_size = FFI::MemoryPointer.new(:uint32)
success = GetTokenInformation(process_token.handle.handle, :TokenElevation, elevation_result, 4, elevation_result_size)
diff --git a/lib/chef/win32_service_constants.rb b/lib/chef/win32_service_constants.rb
new file mode 100644
index 0000000000..4b5eb34327
--- /dev/null
+++ b/lib/chef/win32_service_constants.rb
@@ -0,0 +1,143 @@
+class Chef
+ module Win32ServiceConstants
+ SC_MANAGER_ALL_ACCESS = 0xF003F
+ SC_MANAGER_CREATE_SERVICE = 0x0002
+ SC_MANAGER_CONNECT = 0x0001
+ SC_MANAGER_ENUMERATE_SERVICE = 0x0004
+ SC_MANAGER_LOCK = 0x0008
+ SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
+ SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
+ SC_STATUS_PROCESS_INFO = 0
+ SC_ENUM_PROCESS_INFO = 0
+
+ # Service control action types
+ SC_ACTION_NONE = 0
+ SC_ACTION_RESTART = 1
+ SC_ACTION_REBOOT = 2
+ SC_ACTION_RUN_COMMAND = 3
+
+ # Service access rights
+ SERVICE_ALL_ACCESS = 0xF01FF
+ SERVICE_CHANGE_CONFIG = 0x0002
+ SERVICE_ENUMERATE_DEPENDENTS = 0x0008
+ SERVICE_INTERROGATE = 0x0080
+ SERVICE_PAUSE_CONTINUE = 0x0040
+ SERVICE_QUERY_CONFIG = 0x0001
+ SERVICE_QUERY_STATUS = 0x0004
+ SERVICE_START = 0x0010
+ SERVICE_STOP = 0x0020
+ SERVICE_USER_DEFINED_CONTROL = 0x0100
+
+ # Service types
+ SERVICE_KERNEL_DRIVER = 0x00000001
+ SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
+ SERVICE_ADAPTER = 0x00000004
+ SERVICE_RECOGNIZER_DRIVER = 0x00000008
+ SERVICE_WIN32_OWN_PROCESS = 0x00000010
+ SERVICE_WIN32_SHARE_PROCESS = 0x00000020
+ SERVICE_WIN32 = 0x00000030
+ SERVICE_INTERACTIVE_PROCESS = 0x00000100
+ SERVICE_DRIVER = 0x0000000B
+ SERVICE_TYPE_ALL = 0x0000013F
+
+ # Error control
+ SERVICE_ERROR_IGNORE = 0x00000000
+ SERVICE_ERROR_NORMAL = 0x00000001
+ SERVICE_ERROR_SEVERE = 0x00000002
+ SERVICE_ERROR_CRITICAL = 0x00000003
+
+ # Start types
+ SERVICE_BOOT_START = 0x00000000
+ SERVICE_SYSTEM_START = 0x00000001
+ SERVICE_AUTO_START = 0x00000002
+ SERVICE_DEMAND_START = 0x00000003
+ SERVICE_DISABLED = 0x00000004
+
+ # Service control
+
+ SERVICE_CONTROL_STOP = 0x00000001
+ SERVICE_CONTROL_PAUSE = 0x00000002
+ SERVICE_CONTROL_CONTINUE = 0x00000003
+ SERVICE_CONTROL_INTERROGATE = 0x00000004
+ SERVICE_CONTROL_SHUTDOWN = 0x00000005
+ SERVICE_CONTROL_PARAMCHANGE = 0x00000006
+ SERVICE_CONTROL_NETBINDADD = 0x00000007
+ SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
+ SERVICE_CONTROL_NETBINDENABLE = 0x00000009
+ SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
+ SERVICE_CONTROL_DEVICEEVENT = 0x0000000B
+ SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C
+ SERVICE_CONTROL_POWEREVENT = 0x0000000D
+ SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E
+ SERVICE_CONTROL_PRESHUTDOWN = 0x0000000F
+ SERVICE_CONTROL_TIMECHANGE = 0x00000010
+ SERVICE_CONTROL_TRIGGEREVENT = 0x00000020
+
+ # Service controls accepted
+
+ SERVICE_ACCEPT_STOP = 0x00000001
+ SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
+ SERVICE_ACCEPT_SHUTDOWN = 0x00000004
+ SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
+ SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
+ SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
+ SERVICE_ACCEPT_POWEREVENT = 0x00000040
+ SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
+ SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
+ SERVICE_ACCEPT_TIMECHANGE = 0x00000200
+ SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
+
+ # Service states
+ SERVICE_ACTIVE = 0x00000001
+ SERVICE_INACTIVE = 0x00000002
+ SERVICE_STATE_ALL = 0x00000003
+
+ # Service current states
+ SERVICE_STOPPED = 0x00000001
+ SERVICE_START_PENDING = 0x00000002
+ SERVICE_STOP_PENDING = 0x00000003
+ SERVICE_RUNNING = 0x00000004
+ SERVICE_CONTINUE_PENDING = 0x00000005
+ SERVICE_PAUSE_PENDING = 0x00000006
+ SERVICE_PAUSED = 0x00000007
+
+ # Info levels
+ SERVICE_CONFIG_DESCRIPTION = 1
+ SERVICE_CONFIG_FAILURE_ACTIONS = 2
+ SERVICE_CONFIG_DELAYED_AUTO_START_INFO = 3
+ SERVICE_CONFIG_FAILURE_ACTIONS_FLAG = 4
+ SERVICE_CONFIG_SERVICE_SID_INFO = 5
+ SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO = 6
+ SERVICE_CONFIG_PRESHUTDOWN_INFO = 7
+
+ # Configuration
+ SERVICE_NO_CHANGE = 0xffffffff
+
+ # Misc
+
+ WAIT_OBJECT_0 = 0
+ WAIT_TIMEOUT = 0x00000102
+ INFINITE = 0xFFFFFFFF
+
+ IDLE_CONTROL_CODE = 0
+
+ DELETE = 0x00010000
+ FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
+ FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200
+
+ NO_ERROR = 0
+
+ SE_PRIVILEGE_ENABLED = 0x00000002
+ TOKEN_ADJUST_PRIVILEGES = 0x0020
+ TOKEN_QUERY = 0x0008
+
+ # Errors
+
+ ERROR_INSUFFICIENT_BUFFER = 122
+ ERROR_MORE_DATA = 234
+ ERROR_FILE_NOT_FOUND = 2
+ ERROR_RESOURCE_TYPE_NOT_FOUND = 1813
+ ERROR_RESOURCE_NAME_NOT_FOUND = 1814
+ WAIT_FAILED = 0xFFFFFFFF
+ end
+end
diff --git a/omnibus/.kitchen.yml b/omnibus/.kitchen.yml
index a14d3498de..56b11de3c3 100644
--- a/omnibus/.kitchen.yml
+++ b/omnibus/.kitchen.yml
@@ -39,10 +39,6 @@ platforms:
run_list: yum-epel::default
- name: centos-7.2
run_list: yum-epel::default
- - name: debian-6.0.8
- run_list: apt::default
- - name: debian-7.9
- run_list: apt::default
- name: debian-8.2
run_list: apt::default
- name: freebsd-9.3
@@ -73,6 +69,8 @@ platforms:
#
# KITCHEN_LOCAL_YAML=.kitchen.vmware.yml kitchen converge chefdk-macosx-109
#
+
+ # OSX
<% %w(
10.9
10.10
@@ -86,9 +84,15 @@ platforms:
- ['../../omnibus', '/Users/vagrant/omnibus']
- ['../../omnibus-software', '/Users/vagrant/omnibus-software']
<% end %>
- - name: windows-2012r2-standard
+
+ <% %w(
+ 10-enterprise
+ server-2012r2-standard
+ ).each do |win_version| %>
+ # Windows 64-bit
+ - name: windows-<%= win_version %>
driver:
- box: chef/windows-server-2012r2-standard # private
+ box: chef/windows-<%= win_version %> # private
synced_folders:
# We have to mount this repos enclosing folder as the Omnibus build
# gets cranky if the mounted Chef source folder is a symlink. This
@@ -102,16 +106,14 @@ platforms:
build_user_group: Administrators
build_user_password: vagrant
chef_omnibus_root: /opscode/angrychef
+
+ # Windows 32-bit
# By adding an `i386` to the name the Omnibus cookbook's `load-omnibus-toolchain.bat`
# will load the 32-bit version of the MinGW toolchain.
- - name: windows-2012r2-standard-i386
+ - name: windows-<%= win_version %>-i386
driver:
- box: chef/windows-server-2012r2-standard # private
+ box: chef/windows-<%= win_version %> # private
synced_folders:
- # We have to mount this repos enclosing folder as the Omnibus build
- # gets cranky if the mounted ChefDK source folder is a symlink. This
- # mounts at `C:\vagrant\code` and the ChefDK source folder is available
- # at `C:\vagrant\code\chef-dk`
- ['../..', '/vagrant/code']
provisioner:
attributes:
@@ -120,6 +122,7 @@ platforms:
build_user_group: Administrators
build_user_password: vagrant
chef_omnibus_root: /opscode/angrychef
+ <% end %>
suites:
# - name: angrychef
diff --git a/omnibus/Gemfile b/omnibus/Gemfile
index 652a6e69b8..dbf7409032 100644
--- a/omnibus/Gemfile
+++ b/omnibus/Gemfile
@@ -2,7 +2,6 @@ source "https://rubygems.org"
gem "omnibus", git: "https://github.com/chef/omnibus"
gem "omnibus-software", git: "https://github.com/chef/omnibus-software"
-gem "license_scout", git: "https://github.com/chef/license_scout"
gem "pedump"
diff --git a/omnibus/Gemfile.lock b/omnibus/Gemfile.lock
index 11cb4a1938..0a400af685 100644
--- a/omnibus/Gemfile.lock
+++ b/omnibus/Gemfile.lock
@@ -1,22 +1,13 @@
GIT
- remote: https://github.com/chef/license_scout
- revision: 0e89df12ad6bc451924610dd6a570fc264fde15e
- specs:
- license_scout (0.1.3)
- ffi-yajl (~> 2.2)
- mixlib-shellout (~> 2.2)
- toml-rb (~> 1.0)
-
-GIT
remote: https://github.com/chef/omnibus
- revision: 52393d7cab443b61790f94c62775d9032d283497
+ revision: 68c301587d8856c6ec4445a24ec49365bb22a314
specs:
- omnibus (5.6.1)
+ omnibus (5.6.8)
aws-sdk (~> 2)
chef-sugar (~> 3.3)
cleanroom (~> 1.0)
ffi-yajl (~> 2.2)
- license_scout
+ license_scout (~> 1.0)
mixlib-shellout (~> 2.0)
mixlib-versioning
ohai (~> 8.0)
@@ -26,7 +17,7 @@ GIT
GIT
remote: https://github.com/chef/omnibus-software
- revision: aa4162c2f7a4e8e5cf9d961e060d5a48a15a5e63
+ revision: 4ef2d1a5b9162f4f5f52617d2a0122796b4f3c43
specs:
omnibus-software (4.0.0)
chef-sugar (>= 3.4.0)
@@ -37,15 +28,14 @@ GEM
specs:
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
- artifactory (2.8.2)
awesome_print (1.8.0)
- aws-sdk (2.10.45)
- aws-sdk-resources (= 2.10.45)
- aws-sdk-core (2.10.45)
+ aws-sdk (2.10.128)
+ aws-sdk-resources (= 2.10.128)
+ aws-sdk-core (2.10.128)
aws-sigv4 (~> 1.0)
jmespath (~> 1.0)
- aws-sdk-resources (2.10.45)
- aws-sdk-core (= 2.10.45)
+ aws-sdk-resources (2.10.128)
+ aws-sdk-core (= 2.10.128)
aws-sigv4 (1.0.2)
berkshelf (4.3.5)
addressable (~> 2.3, >= 2.3.4)
@@ -69,7 +59,7 @@ GEM
faraday (~> 0.9.1)
httpclient (~> 2.7.0)
ridley (~> 4.5)
- binding_of_caller (0.7.2)
+ binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
buff-config (1.0.1)
buff-extensions (~> 1.0)
@@ -80,18 +70,19 @@ GEM
buff-shell_out (0.2.0)
buff-ruby_engine (~> 0.1.0)
builder (3.2.3)
- byebug (9.1.0)
+ byebug (10.0.0)
celluloid (0.16.0)
timers (~> 4.0.0)
celluloid-io (0.16.2)
celluloid (>= 0.16.0)
nio4r (>= 1.1.0)
- chef-config (13.4.19)
+ chef-config (13.7.16)
addressable
fuzzyurl
mixlib-config (~> 2.0)
mixlib-shellout (~> 2.0)
- chef-sugar (3.5.0)
+ tomlrb (~> 1.2)
+ chef-sugar (3.6.0)
citrus (3.0.2)
cleanroom (1.0.0)
coderay (1.1.2)
@@ -99,9 +90,7 @@ GEM
erubis (2.7.0)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
- ffi (1.9.18)
- ffi (1.9.18-x64-mingw32)
- ffi (1.9.18-x86-mingw32)
+ ffi (1.9.21)
ffi-yajl (2.3.1)
libyajl2 (~> 1.2)
fuzzyurl (0.9.0)
@@ -109,9 +98,8 @@ GEM
ffi (>= 1.0.1)
gyoku (1.3.1)
builder (>= 2.1.2)
- hashie (3.5.6)
+ hashie (3.5.7)
hitimes (1.2.6)
- hitimes (1.2.6-x86-mingw32)
httpclient (2.7.2)
iostruct (0.0.4)
ipaddress (0.8.3)
@@ -120,41 +108,41 @@ GEM
kitchen-vagrant (0.19.0)
test-kitchen (~> 1.4)
libyajl2 (1.2.0)
+ license_scout (1.0.0)
+ ffi-yajl (~> 2.2)
+ mixlib-shellout (~> 2.2)
+ toml-rb (~> 1.0)
little-plugger (1.1.4)
logging (2.2.2)
little-plugger (~> 1.1)
multi_json (~> 1.10)
- method_source (0.8.2)
+ method_source (0.9.0)
minitar (0.6.1)
mixlib-archive (0.4.1)
mixlib-log
mixlib-authentication (1.4.2)
mixlib-cli (1.7.0)
mixlib-config (2.2.4)
- mixlib-install (2.1.12)
- artifactory
+ mixlib-install (3.9.0)
mixlib-shellout
mixlib-versioning
thor
mixlib-log (1.7.1)
mixlib-shellout (2.3.2)
- mixlib-shellout (2.3.2-universal-mingw32)
- win32-process (~> 0.8.2)
- wmi-lite (~> 1.0)
mixlib-versioning (1.2.2)
molinillo (0.4.5)
- multi_json (1.12.2)
+ multi_json (1.13.1)
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (4.2.0)
net-ssh-gateway (1.3.0)
net-ssh (>= 2.6.5)
- nio4r (2.1.0)
+ nio4r (2.2.0)
nori (2.6.0)
- octokit (4.7.0)
+ octokit (4.8.0)
sawyer (~> 0.8.0, >= 0.5.3)
- ohai (8.24.1)
+ ohai (8.26.1)
chef-config (>= 12.5.0.alpha.1, < 14)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
@@ -172,19 +160,18 @@ GEM
multipart-post (~> 2.0.0)
progressbar
zhexdump (>= 0.0.2)
- plist (3.3.0)
- progressbar (1.8.2)
- pry (0.10.4)
+ plist (3.4.0)
+ progressbar (1.9.0)
+ pry (0.11.3)
coderay (~> 1.1.0)
- method_source (~> 0.8.1)
- slop (~> 3.4)
- pry-byebug (3.5.0)
- byebug (~> 9.1)
+ method_source (~> 0.9.0)
+ pry-byebug (3.6.0)
+ byebug (~> 10.0)
pry (~> 0.10)
pry-stack_explorer (0.4.9.2)
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
- public_suffix (3.0.0)
+ public_suffix (3.0.1)
retryable (2.0.4)
ridley (4.6.1)
addressable
@@ -204,37 +191,36 @@ GEM
retryable (~> 2.0)
semverse (~> 1.1)
varia_model (~> 0.4.0)
- ruby-progressbar (1.8.3)
+ ruby-progressbar (1.9.0)
rubyntlm (0.6.2)
rubyzip (1.2.1)
- safe_yaml (1.0.4)
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.17.0)
- mixlib-install (>= 1.2, < 3.0)
+ test-kitchen (1.20.0)
+ mixlib-install (~> 3.6)
mixlib-shellout (>= 1.2, < 3.0)
net-scp (~> 1.1)
net-ssh (>= 2.9, < 5.0)
net-ssh-gateway (~> 1.2)
- safe_yaml (~> 1.0)
thor (~> 0.19, < 0.19.2)
+ winrm (~> 2.0)
+ winrm-elevated (~> 1.0)
+ winrm-fs (~> 1.1.0)
thor (0.19.1)
timers (4.0.4)
hitimes
- toml-rb (1.0.0)
+ toml-rb (1.1.1)
citrus (~> 3.0, > 3.0)
+ tomlrb (1.2.6)
varia_model (0.4.1)
buff-extensions (~> 1.0)
hashie (>= 2.0.2, < 4.0.0)
- win32-process (0.8.3)
- ffi (>= 1.0.0)
winrm (2.2.3)
builder (>= 2.1.2)
erubis (~> 2.7)
@@ -244,7 +230,10 @@ GEM
logging (>= 1.6.1, < 3.0)
nori (~> 2.0)
rubyntlm (~> 0.6.0, >= 0.6.1)
- winrm-fs (1.0.1)
+ winrm-elevated (1.1.0)
+ winrm (~> 2.0)
+ winrm-fs (~> 1.0)
+ winrm-fs (1.1.1)
erubis (~> 2.7)
logging (>= 1.6.1, < 3.0)
rubyzip (~> 1.1)
@@ -254,13 +243,10 @@ GEM
PLATFORMS
ruby
- x64-mingw32
- x86-mingw32
DEPENDENCIES
berkshelf (~> 4.0)
kitchen-vagrant (~> 0.19.0)
- license_scout!
omnibus!
omnibus-software!
pedump
@@ -271,4 +257,4 @@ DEPENDENCIES
winrm-fs (~> 1.0)
BUNDLED WITH
- 1.15.4
+ 1.15.1
diff --git a/omnibus/resources/chef/msi/source.wxs.erb b/omnibus/resources/chef/msi/source.wxs.erb
index c49a8324f9..2249262b1f 100644
--- a/omnibus/resources/chef/msi/source.wxs.erb
+++ b/omnibus/resources/chef/msi/source.wxs.erb
@@ -28,6 +28,13 @@
<Media Id="1" Cabinet="ChefClient.cab" EmbedCab="yes" CompressionLevel="high" />
+ <!--
+ Take advantage of Windows Installer 5.0 feature (if available) to disable
+ checkpointing and other costings that take significant amounts of time
+ ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd408005(v=vs.85).aspx
+ -->
+ <Property Id="MSIFASTINSTALL" Value="7" />
+
<Property Id="CHEF_SERVICE_OPTIONS_RADIO_BUTTON_GROUP" Value="None" />
<!--
diff --git a/omnibus_overrides.rb b/omnibus_overrides.rb
index 5e2f1af4d9..8da7dc9940 100644
--- a/omnibus_overrides.rb
+++ b/omnibus_overrides.rb
@@ -1,22 +1,22 @@
# THIS IS NOW HAND MANAGED, JUST EDIT THE THING
# .travis.yml and appveyor.yml consume this,
# try to keep it machine-parsable.
-override :rubygems, version: "2.6.13"
+override :rubygems, version: "2.6.14"
override :bundler, version: "1.15.4"
-override "nokogiri", version: "1.8.0"
+override "nokogiri", version: "1.8.1"
override "libffi", version: "3.2.1"
-override "libiconv", version: "1.14"
+override "libiconv", version: "1.15"
override "liblzma", version: "5.2.3"
override "libtool", version: "2.4.2"
-override "libxml2", version: "2.9.4"
-override "libxslt", version: "1.1.29"
-override "libyaml", version: "0.1.6"
+override "libxml2", version: "2.9.5"
+override "libxslt", version: "1.1.30"
+override "libyaml", version: "0.1.7"
override "makedepend", version: "1.0.5"
override "ncurses", version: "5.9"
override "pkg-config-lite", version: "0.28-1"
-override "ruby", version: "2.4.2"
+override "ruby", version: "2.4.3"
override "ruby-windows-devkit-bash", version: "3.1.23-4-msys-1.0.18"
override "util-macros", version: "1.19.0"
override "xproto", version: "7.0.28"
override "zlib", version: "1.2.11"
-override "openssl", version: "1.0.2j"
+override "openssl", version: "1.0.2n"
diff --git a/spec/data/client.d_00/02-strings.rb b/spec/data/client.d_00/02-strings.rb
new file mode 100644
index 0000000000..7d9a49268c
--- /dev/null
+++ b/spec/data/client.d_00/02-strings.rb
@@ -0,0 +1,2 @@
+# 02-strings.rb
+something '/foo/bar'
diff --git a/spec/functional/assets/chefinittest b/spec/functional/assets/chefinittest
index 79e064cd5f..b67abbfa43 100755
--- a/spec/functional/assets/chefinittest
+++ b/spec/functional/assets/chefinittest
@@ -1,15 +1,17 @@
#!/bin/ksh
+TMPDIR="${TMPDIR:-/tmp}"
+
function create_chef_txt {
- touch /tmp/chefinittest.txt
+ touch $TMPDIR/chefinittest.txt
}
function delete_chef_txt {
- rm /tmp/chefinittest.txt
+ rm $TMPDIR/chefinittest.txt
}
function rename_chef_txt {
- mv /tmp/chefinittest.txt /tmp/$1
+ mv $TMPDIR/chefinittest.txt $TMPDIR/$1
}
case "$1" in
@@ -20,7 +22,7 @@ stop )
delete_chef_txt
;;
status )
- [ -f /tmp/chefinittest.txt ] || [ -f /tmp/chefinittest_reload.txt ] || [ -f /tmp/chefinittest_restart.txt ]
+ [ -f $TMPDIR/chefinittest.txt ] || [ -f $TMPDIR/chefinittest_reload.txt ] || [ -f $TMPDIR/chefinittest_restart.txt ]
;;
reload )
rename_chef_txt "chefinittest_reload.txt"
diff --git a/spec/functional/http/simple_spec.rb b/spec/functional/http/simple_spec.rb
index 421045693a..e792cc8d75 100644
--- a/spec/functional/http/simple_spec.rb
+++ b/spec/functional/http/simple_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Lamont Granquist (<lamont@chef.io>)
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,11 +26,17 @@ describe Chef::HTTP::Simple do
let(:http_client) { described_class.new(source) }
let(:http_client_disable_gzip) { described_class.new(source, { :disable_gzip => true } ) }
+ before(:all) do
+ start_tiny_server(RequestTimeout: 1)
+ end
+
before(:each) do
- start_tiny_server
+ Chef::Config[:rest_timeout] = 2
+ Chef::Config[:http_retry_delay] = 0
+ Chef::Config[:http_retry_count] = 0
end
- after(:each) do
+ after(:all) do
stop_tiny_server
end
@@ -46,10 +52,10 @@ describe Chef::HTTP::Simple do
end
shared_examples_for "validates content length and throws an exception" do
- it "successfully downloads a streaming request" do
+ it "a streaming request throws a content length exception" do
expect { http_client.streaming_request(source) }.to raise_error(Chef::Exceptions::ContentLengthMismatch)
end
- it "successfully does a non-streaming GET request" do
+ it "a non-streaming GET request throws a content length exception" do
expect { http_client.get(source) }.to raise_error(Chef::Exceptions::ContentLengthMismatch)
end
end
diff --git a/spec/functional/knife/ssh_spec.rb b/spec/functional/knife/ssh_spec.rb
index 9d6fd3ae10..3defbe781f 100644
--- a/spec/functional/knife/ssh_spec.rb
+++ b/spec/functional/knife/ssh_spec.rb
@@ -181,11 +181,11 @@ describe Chef::Knife::Ssh do
it "uses the ssh_attribute" do
@knife.run
- expect(@knife.get_ssh_attribute({ "knife_config" => "ec2.public_hostname" })).to eq("ec2.public_hostname")
+ expect(@knife.get_ssh_attribute({ "target" => "ec2.public_hostname" })).to eq("ec2.public_hostname")
end
end
- context "when knife[:ssh_attribute] is not provided]" do
+ context "when knife[:ssh_attribute] is not provided" do
before do
setup_knife(["*:*", "uptime"])
Chef::Config[:knife][:ssh_attribute] = nil
@@ -199,22 +199,69 @@ describe Chef::Knife::Ssh do
context "when -a ec2.public_public_hostname is provided" do
before do
- setup_knife(["-a ec2.public_hostname", "*:*", "uptime"])
+ setup_knife(["-a", "ec2.public_hostname", "*:*", "uptime"])
Chef::Config[:knife][:ssh_attribute] = nil
end
it "should use the value on the command line" do
@knife.run
- expect(@knife.config[:attribute]).to eq("ec2.public_hostname")
+ expect(@knife.config[:ssh_attribute]).to eq("ec2.public_hostname")
end
it "should override what is set in knife.rb" do
# This is the setting imported from knife.rb
Chef::Config[:knife][:ssh_attribute] = "fqdn"
# Then we run knife with the -a flag, which sets the above variable
- setup_knife(["-a ec2.public_hostname", "*:*", "uptime"])
+ setup_knife(["-a", "ec2.public_hostname", "*:*", "uptime"])
@knife.run
- expect(@knife.config[:attribute]).to eq("ec2.public_hostname")
+ expect(@knife.config[:ssh_attribute]).to eq("ec2.public_hostname")
+ end
+ end
+ end
+
+ describe "prefix" do
+ context "when knife[:prefix_attribute] is set" do
+ before do
+ setup_knife(["*:*", "uptime"])
+ Chef::Config[:knife][:prefix_attribute] = "name"
+ end
+
+ it "uses the prefix_attribute" do
+ @knife.run
+ expect(@knife.get_prefix_attribute({ "prefix" => "name" })).to eq("name")
+ end
+ end
+
+ context "when knife[:prefix_attribute] is not provided" do
+ before do
+ setup_knife(["*:*", "uptime"])
+ Chef::Config[:knife][:prefix_attribute] = nil
+ end
+
+ it "falls back to nil" do
+ @knife.run
+ expect(@knife.get_prefix_attribute({})).to eq(nil)
+ end
+ end
+
+ context "when --prefix-attribute ec2.public_public_hostname is provided" do
+ before do
+ setup_knife(["--prefix-attribute", "ec2.public_hostname", "*:*", "uptime"])
+ Chef::Config[:knife][:prefix_attribute] = nil
+ end
+
+ it "should use the value on the command line" do
+ @knife.run
+ expect(@knife.config[:prefix_attribute]).to eq("ec2.public_hostname")
+ end
+
+ it "should override what is set in knife.rb" do
+ # This is the setting imported from knife.rb
+ Chef::Config[:knife][:prefix_attribute] = "fqdn"
+ # Then we run knife with the -b flag, which sets the above variable
+ setup_knife(["--prefix-attribute", "ec2.public_hostname", "*:*", "uptime"])
+ @knife.run
+ expect(@knife.config[:prefix_attribute]).to eq("ec2.public_hostname")
end
end
end
@@ -305,7 +352,7 @@ describe Chef::Knife::Ssh do
Chef::Config[:chef_server_url] = "http://localhost:9000"
@api.post("/search/node?q=*:*&start=0&rows=1000", 200) do
- %({"total":1, "start":0, "rows":[{"data": {"fqdn":"the.fqdn", "config": "the_public_hostname", "knife_config": "the_public_hostname" }}]})
+ %({"total":1, "start":0, "rows":[{"data": {"fqdn":"the.fqdn", "target": "the_public_hostname"}}]})
end
end
diff --git a/spec/functional/mixin/powershell_out_spec.rb b/spec/functional/mixin/powershell_out_spec.rb
index 7fc8dc5957..d6fba5b084 100644
--- a/spec/functional/mixin/powershell_out_spec.rb
+++ b/spec/functional/mixin/powershell_out_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,16 +22,8 @@ describe Chef::Mixin::PowershellOut, windows_only: true do
include Chef::Mixin::PowershellOut
describe "#powershell_out" do
- context "for windows version less than 10", windows_lt_10: true do
- it "runs a powershell command and collects stdout" do
- expect(powershell_out("get-process").run_command.stdout).to match /Handles\s+NPM\(K\)\s+PM\(K\)\s+WS\(K\)\s+VM\(M\)\s+CPU\(s\)\s+Id\s+/
- end
- end
-
- context "for windows version greater than 10", windows_gte_10: true do
- it "runs a powershell command and collects stdout" do
- expect(powershell_out("get-process").run_command.stdout).to match /Handles\s+NPM\(K\)\s+PM\(K\)\s+WS\(K\)\s+CPU\(s\)\s+Id\s+SI\s+ProcessName\s+/
- end
+ it "runs a powershell command and collects stdout" do
+ expect(powershell_out("get-process").run_command.stdout).to match /Handles/
end
it "does not raise exceptions when the command is invalid" do
@@ -40,16 +32,8 @@ describe Chef::Mixin::PowershellOut, windows_only: true do
end
describe "#powershell_out!" do
- context "for windows version less than 10", windows_lt_10: true do
- it "runs a powershell command and collects stdout" do
- expect(powershell_out!("get-process").run_command.stdout).to match /Handles\s+NPM\(K\)\s+PM\(K\)\s+WS\(K\)\s+VM\(M\)\s+CPU\(s\)\s+Id\s+/
- end
- end
-
- context "for windows version less than 10", windows_gte_10: true do
- it "runs a powershell command and collects stdout" do
- expect(powershell_out("get-process").run_command.stdout).to match /Handles\s+NPM\(K\)\s+PM\(K\)\s+WS\(K\)\s+CPU\(s\)\s+Id\s+SI\s+ProcessName\s+/
- end
+ it "runs a powershell command and collects stdout" do
+ expect(powershell_out!("get-process").run_command.stdout).to match /Handles/
end
it "raises exceptions when the command is invalid" do
diff --git a/spec/functional/rebooter_spec.rb b/spec/functional/rebooter_spec.rb
index a28491cc0b..36961593b0 100644
--- a/spec/functional/rebooter_spec.rb
+++ b/spec/functional/rebooter_spec.rb
@@ -35,8 +35,9 @@ describe Chef::Platform::Rebooter do
resource
end
+ let(:node) { Chef::Node.new }
+
let(:run_context) do
- node = Chef::Node.new
events = Chef::EventDispatch::Dispatcher.new
Chef::RunContext.new(node, {}, events)
end
@@ -44,7 +45,8 @@ describe Chef::Platform::Rebooter do
let(:expected) do
{
:windows => "#{ENV['SYSTEMROOT']}/System32/shutdown.exe /r /t 300 /c \"rebooter spec test\"",
- :linux => 'shutdown -r +5 "rebooter spec test"',
+ :linux => 'shutdown -r +5 "rebooter spec test" &',
+ :solaris => 'shutdown -i6 -g5 -y "rebooter spec test" &',
}
end
@@ -69,8 +71,9 @@ describe Chef::Platform::Rebooter do
end
shared_context "test a reboot method" do
- def test_rebooter_method(method_sym, is_windows, expected_reboot_str)
+ def test_rebooter_method(method_sym, is_windows, is_solaris, expected_reboot_str)
allow(ChefConfig).to receive(:windows?).and_return(is_windows)
+ node.automatic["os"] = node.automatic["platform"] = node.automatic["platform_family"] = "solaris2" if is_solaris
expect(rebooter).to receive(:shell_out!).once.with(expected_reboot_str)
expect(rebooter).to receive(:raise).with(Chef::Exceptions::Reboot)
expect(rebooter).to receive(method_sym).once.and_call_original
@@ -81,24 +84,32 @@ 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", :windows_only do
- test_rebooter_method(:reboot_if_needed!, true, expected[:windows])
+ it "should produce the correct string on Windows" do
+ test_rebooter_method(:reboot_if_needed!, true, false, expected[:windows])
+ end
+
+ it "should produce a SysV-like shutdown on solaris" do
+ test_rebooter_method(:reboot_if_needed!, false, true, expected[:solaris])
end
- it "should produce the correct (Linux-specific) string on non-Windows" do
- test_rebooter_method(:reboot_if_needed!, false, expected[:linux])
+ it "should produce a BSD-like shutdown by default" do
+ test_rebooter_method(:reboot_if_needed!, false, false, expected[:linux])
end
end
describe "when using #reboot!" do
include_context "test a reboot method"
- it "should produce the correct string on Windows", :windows_only do
- test_rebooter_method(:reboot!, true, expected[:windows])
+ it "should produce the correct string on Windows" do
+ test_rebooter_method(:reboot!, true, false, expected[:windows])
+ end
+
+ it "should produce a SysV-like shutdown on solaris" do
+ test_rebooter_method(:reboot!, false, true, expected[:solaris])
end
- it "should produce the correct (Linux-specific) string on non-Windows" do
- test_rebooter_method(:reboot!, false, expected[:linux])
+ it "should produce a BSD-like shutdown by default" do
+ test_rebooter_method(:reboot!, false, false, expected[:linux])
end
end
end
diff --git a/spec/functional/resource/package_spec.rb b/spec/functional/resource/apt_package_spec.rb
index 0f01a751ec..7c58937ee2 100644
--- a/spec/functional/resource/package_spec.rb
+++ b/spec/functional/resource/apt_package_spec.rb
@@ -1,7 +1,7 @@
# encoding: UTF-8
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2013-2016, Chef Software, Inc.
+# Copyright:: Copyright 2013-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -92,7 +92,7 @@ metadata = { :unix_only => true,
:arch => "x86_64" # test packages are 64bit
}
-describe Chef::Resource::Package, metadata do
+describe Chef::Resource::AptPackage, metadata do
include Chef::Mixin::ShellOut
context "with a remote package source" do
@@ -143,7 +143,7 @@ describe Chef::Resource::Package, metadata do
end
def base_resource
- r = Chef::Resource::Package.new("chef-integration-test", run_context)
+ r = Chef::Resource::AptPackage.new("chef-integration-test", run_context)
# The apt repository in the spec data is not gpg signed, so we need to
# force apt to accept the package:
r.options("--force-yes")
diff --git a/spec/functional/resource/bff_spec.rb b/spec/functional/resource/bff_spec.rb
index e7f7540e5a..0b45e097af 100644
--- a/spec/functional/resource/bff_spec.rb
+++ b/spec/functional/resource/bff_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Prabhu Das (<prabhu.das@clogeny.com>)
-# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# Copyright:: Copyright 2013-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -62,7 +62,7 @@ describe Chef::Resource::BffPackage, :requires_root, :external => ohai[:platform
context "package install action with options" do
it "should install a package" do
- new_resource.options("-e/tmp/installp.log")
+ new_resource.options("-e#{Dir.tmpdir}/installp.log")
new_resource.run_action(:install)
bff_pkg_should_be_installed(new_resource)
end
@@ -108,7 +108,7 @@ describe Chef::Resource::BffPackage, :requires_root, :external => ohai[:platform
end
it "should remove an installed package" do
- new_resource.options("-e/tmp/installp.log")
+ new_resource.options("-e#{Dir.tmpdir}/installp.log")
new_resource.run_action(:remove)
bff_pkg_should_be_removed(new_resource)
end
diff --git a/spec/functional/resource/deploy_revision_spec.rb b/spec/functional/resource/deploy_revision_spec.rb
deleted file mode 100644
index 572609d8ff..0000000000
--- a/spec/functional/resource/deploy_revision_spec.rb
+++ /dev/null
@@ -1,881 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-require "tmpdir"
-
-# Deploy relies heavily on symlinks, so it doesn't work on windows.
-describe Chef::Resource::DeployRevision, :unix_only => true, :requires_git => true do
-
- let(:file_cache_path) { Dir.mktmpdir }
- let(:deploy_directory) { Dir.mktmpdir }
-
- # By making restart or other operations write to this file, we can externally
- # track the order in which those operations happened.
- let(:observe_order_file) { Tempfile.new("deploy-resource-observe-operations") }
-
- before do
- Chef::Log.level = :info
- @old_file_cache_path = Chef::Config[:file_cache_path]
- Chef::Config[:file_cache_path] = file_cache_path
- end
-
- after do
- Chef::Config[:file_cache_path] = @old_file_cache_path
- FileUtils.remove_entry_secure deploy_directory if File.exist?(deploy_directory)
- FileUtils.remove_entry_secure file_cache_path
- observe_order_file.close
- FileUtils.remove_entry_secure observe_order_file.path
- end
-
- before(:all) do
- @ohai = Ohai::System.new
- @ohai.all_plugins(%w{platform os})
- end
-
- let(:node) do
- Chef::Node.new.tap do |n|
- n.name "rspec-test"
- n.consume_external_attrs(@ohai.data, {})
- end
- end
-
- let(:event_dispatch) { Chef::EventDispatch::Dispatcher.new }
- let(:run_context) { Chef::RunContext.new(node, {}, event_dispatch) }
-
- # These tests use git's bundle feature, which is a way to export an entire
- # git repo (or subset of commits) as a single file.
- #
- # Generally you can treat a git bundle as a regular git remote.
- #
- # See also: http://git-scm.com/2010/03/10/bundles.html
- let(:git_bundle_repo) { File.expand_path("git_bundles/sinatra-test-app.gitbundle", CHEF_SPEC_DATA) }
-
- let(:git_bundle_with_in_repo_callbacks) { File.expand_path("git_bundles/sinatra-test-app-with-callback-files.gitbundle", CHEF_SPEC_DATA) }
-
- let(:git_bundle_with_in_repo_symlinks) { File.expand_path("git_bundles/sinatra-test-app-with-symlinks.gitbundle", CHEF_SPEC_DATA) }
-
- # This is the fourth version
- let(:latest_rev) { "3eb5ca6c353c83d9179dd3b29347539829b401f3" }
-
- # This is the third version
- let(:previous_rev) { "6d19a6dbecc8e37f5b2277345885c0c783eb8fb1" }
-
- # This is the second version
- let(:second_rev) { "0827e1b0e5043608ac0a824da5c558e252154ad0" }
-
- # This is the sixth version, it is on the "with-deploy-scripts" branch
- let(:rev_with_in_repo_callbacks) { "2404d015882659754bdb93ad6e4b4d3d02691a82" }
-
- # This is the fifth version in the "with-symlinks" branch
- let(:rev_with_in_repo_symlinks) { "5a4748c52aaea8250b4346a9b8ede95ee3755e28" }
-
- # Read values from the +observe_order_file+ and split each line. This way you
- # can see in which order things really happened.
- def actual_operations_order
- IO.read(observe_order_file.path).split("\n").map(&:strip)
- end
-
- # 1. touch `restart.txt` in cwd so we know that the command is run with the
- # right cwd.
- # 2. Append +tag+ to the `observe_order_file` so we can check the order in
- # which operations happen later in the test.
- def shell_restart_command(tag)
- "touch restart.txt && echo '#{tag}' >> #{observe_order_file.path}"
- end
-
- let(:basic_deploy_resource) do
- Chef::Resource::DeployRevision.new(deploy_directory, run_context).tap do |r|
- r.name "deploy-revision-unit-test"
- r.repo git_bundle_repo
- r.symlink_before_migrate({})
- r.symlinks({})
- end
- end
-
- let(:deploy_to_latest_rev) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(latest_rev)
- r.restart_command shell_restart_command(:deploy_to_latest_rev)
- end
- end
-
- let(:deploy_to_previous_rev) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(previous_rev)
- r.restart_command shell_restart_command(:deploy_to_previous_rev)
- end
- end
-
- let(:deploy_to_latest_rev_again) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(latest_rev)
- r.restart_command shell_restart_command(:deploy_to_latest_rev_again)
- end
- end
-
- let(:deploy_to_previous_rev_again) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(previous_rev)
- r.restart_command shell_restart_command(:deploy_to_previous_rev_again)
- end
- end
-
- let(:deploy_to_second_rev) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(second_rev)
- r.restart_command shell_restart_command(:deploy_to_second_rev)
- end
- end
-
- let(:deploy_to_second_rev_again) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(second_rev)
- r.restart_command shell_restart_command(:deploy_to_second_rev_again)
- end
- end
-
- let(:deploy_to_second_rev_again_again) do
- basic_deploy_resource.dup.tap do |r|
- r.revision(second_rev)
- r.restart_command shell_restart_command(:deploy_to_second_rev_again_again)
- end
- end
-
- # Computes the full path for +path+ relative to the deploy directory
- def rel_path(path)
- File.expand_path(path, deploy_directory)
- end
-
- def actual_current_rev
- Dir.chdir(rel_path("current")) do
- `git rev-parse HEAD`.strip
- end
- end
-
- def self.the_app_is_deployed_at_revision(target_rev_spec)
- it "deploys the app to the target revision (#{target_rev_spec})" do
- target_rev = send(target_rev_spec)
-
- expect(File).to exist(rel_path("current"))
-
- expect(actual_current_rev).to eq(target_rev)
-
- # Is the app code actually there?
- expect(File).to exist(rel_path("current/app/app.rb"))
- end
- end
-
- context "when deploying a simple app" do
- describe "for the first time, with the required directory layout precreated" do
- before do
- FileUtils.mkdir_p(rel_path("releases"))
- FileUtils.mkdir_p(rel_path("shared"))
- deploy_to_latest_rev.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "restarts the application" do
- expect(File).to exist(rel_path("current/restart.txt"))
- expect(actual_operations_order).to eq(%w{deploy_to_latest_rev})
- end
-
- it "is marked as updated" do
- expect(deploy_to_latest_rev).to be_updated_by_last_action
- end
- end
-
- describe "back to a previously deployed revision, with the directory structure precreated" do
- before do
- FileUtils.mkdir_p(rel_path("releases"))
- FileUtils.mkdir_p(rel_path("shared"))
-
- deploy_to_latest_rev.run_action(:deploy)
- deploy_to_previous_rev.run_action(:deploy)
- deploy_to_latest_rev_again.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "restarts the application after rolling back" do
- expect(actual_operations_order).to eq(%w{deploy_to_latest_rev deploy_to_previous_rev deploy_to_latest_rev_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_latest_rev_again).to be_updated_by_last_action
- end
-
- it "deploys the right code" do
- expect(IO.read(rel_path("current/app/app.rb"))).to include("this is the fourth version of the app")
- end
- end
-
- describe "for the first time, with no existing directory layout" do
- before do
- deploy_to_latest_rev.run_action(:deploy)
- end
-
- it "creates the required directory tree" do
- expect(File).to be_directory(rel_path("releases"))
- expect(File).to be_directory(rel_path("shared"))
- expect(File).to be_directory(rel_path("releases/#{latest_rev}"))
-
- expect(File).to be_directory(rel_path("current/tmp"))
- expect(File).to be_directory(rel_path("current/config"))
- expect(File).to be_directory(rel_path("current/public"))
-
- expect(File).to be_symlink(rel_path("current"))
- expect(File.readlink(rel_path("current"))).to eq(rel_path("releases/#{latest_rev}"))
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "restarts the application" do
- expect(File).to exist(rel_path("current/restart.txt"))
- expect(actual_operations_order).to eq(%w{deploy_to_latest_rev})
- end
-
- it "is marked as updated" do
- expect(deploy_to_latest_rev).to be_updated_by_last_action
- end
- end
-
- describe "again to the current revision" do
- before do
- deploy_to_latest_rev.run_action(:deploy)
- deploy_to_latest_rev.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "does not restart the app" do
- expect(actual_operations_order).to eq(%w{deploy_to_latest_rev})
- end
-
- it "is not marked updated" do
- expect(deploy_to_latest_rev).not_to be_updated_by_last_action
- end
-
- end
-
- describe "again with force_deploy" do
- before do
- deploy_to_latest_rev.run_action(:force_deploy)
- deploy_to_latest_rev_again.run_action(:force_deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "restarts the app" do
- expect(actual_operations_order).to eq(%w{deploy_to_latest_rev deploy_to_latest_rev_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_latest_rev).to be_updated_by_last_action
- end
-
- end
-
- describe "again to a new revision" do
- before do
- deploy_to_previous_rev.run_action(:deploy)
- deploy_to_latest_rev.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "restarts the application after the new deploy" do
- expect(actual_operations_order).to eq(%w{deploy_to_previous_rev deploy_to_latest_rev})
- end
-
- it "is marked updated" do
- expect(deploy_to_previous_rev).to be_updated_by_last_action
- end
-
- it "leaves the old copy of the app around for rollback" do
- expect(File).to exist(File.join(deploy_directory, "releases", previous_rev))
- end
-
- end
-
- describe "back to a previously deployed revision (implicit rollback)" do
- before do
- deploy_to_latest_rev.run_action(:deploy)
- deploy_to_previous_rev.run_action(:deploy)
- deploy_to_latest_rev_again.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "restarts the application after rolling back" do
- expect(actual_operations_order).to eq(%w{deploy_to_latest_rev deploy_to_previous_rev deploy_to_latest_rev_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_latest_rev_again).to be_updated_by_last_action
- end
-
- it "deploys the right code" do
- expect(IO.read(rel_path("current/app/app.rb"))).to include("this is the fourth version of the app")
- end
- end
-
- describe "back to a previously deployed revision where resource rev == latest revision (explicit rollback)" do
- before do
- deploy_to_previous_rev.run_action(:deploy)
- @previous_rev_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
- deploy_to_latest_rev.run_action(:deploy)
- @latest_rev_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
- deploy_to_latest_rev_again.run_action(:rollback)
- @previous_rev_again_all_releases = deploy_to_latest_rev_again.provider_for_action(:deploy).all_releases
- end
-
- the_app_is_deployed_at_revision(:previous_rev)
-
- it "restarts the application after rolling back" do
- expect(actual_operations_order).to eq(%w{deploy_to_previous_rev deploy_to_latest_rev deploy_to_latest_rev_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_latest_rev_again).to be_updated_by_last_action
- end
-
- it "deploys the right code" do
- expect(IO.read(rel_path("current/app/app.rb"))).to include("this is the third version of the app")
- end
-
- it "all_releases after first deploy should have one entry" do
- expect(@previous_rev_all_releases.length).to eq(1)
- end
-
- it "all_releases after second deploy should have two entries" do
- expect(@latest_rev_all_releases.length).to eq(2)
- end
-
- it "all_releases after rollback should have one entry" do
- expect(@previous_rev_again_all_releases.length).to eq(1)
- end
-
- it "all_releases after rollback should be the same as after the first deploy" do
- expect(@previous_rev_again_all_releases).to eq(@previous_rev_all_releases)
- end
-
- end
-
- describe "back to a previously deployed revision where resource rev == previous revision (explicit rollback)" do
- before do
- deploy_to_previous_rev.run_action(:deploy)
- @previous_rev_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
- deploy_to_latest_rev.run_action(:deploy)
- @latest_rev_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
- deploy_to_previous_rev_again.run_action(:rollback)
- # FIXME: only difference with previous test is using latest_rev_again insetad of previous_rev_again
- @previous_rev_again_all_releases = deploy_to_latest_rev_again.provider_for_action(:deploy).all_releases
- end
-
- the_app_is_deployed_at_revision(:previous_rev)
-
- it "restarts the application after rolling back" do
- expect(actual_operations_order).to eq(%w{deploy_to_previous_rev deploy_to_latest_rev deploy_to_previous_rev_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_previous_rev_again).to be_updated_by_last_action
- end
-
- it "deploys the right code" do
- expect(IO.read(rel_path("current/app/app.rb"))).to include("this is the third version of the app")
- end
-
- it "all_releases after first deploy should have one entry" do
- expect(@previous_rev_all_releases.length).to eq(1)
- end
-
- it "all_releases after second deploy should have two entries" do
- expect(@latest_rev_all_releases.length).to eq(2)
- end
-
- it "all_releases after rollback should have one entry" do
- expect(@previous_rev_again_all_releases.length).to eq(1)
- end
-
- it "all_releases after rollback should be the same as after the first deploy" do
- expect(@previous_rev_again_all_releases).to eq(@previous_rev_all_releases)
- end
- end
-
- describe "back to a previously deployed revision where resource rev == latest revision (explicit rollback)" do
- before do
- deploy_to_second_rev.run_action(:deploy)
- @first_deploy_all_releases = deploy_to_second_rev.provider_for_action(:deploy).all_releases
- deploy_to_previous_rev.run_action(:deploy)
- @second_deploy_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
- deploy_to_previous_rev_again.run_action(:rollback)
- @third_deploy_all_releases = deploy_to_previous_rev_again.provider_for_action(:deploy).all_releases
- deploy_to_latest_rev.run_action(:deploy)
- @fourth_deploy_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
- deploy_to_latest_rev_again.run_action(:rollback)
- @fifth_deploy_all_releases = deploy_to_latest_rev_again.provider_for_action(:deploy).all_releases
- end
-
- the_app_is_deployed_at_revision(:second_rev)
-
- it "restarts the application after rolling back" do
- expect(actual_operations_order).to eq(%w{deploy_to_second_rev deploy_to_previous_rev deploy_to_previous_rev_again deploy_to_latest_rev deploy_to_latest_rev_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_latest_rev_again).to be_updated_by_last_action
- end
-
- it "deploys the right code" do
- expect(IO.read(rel_path("current/app/app.rb"))).to include("this is the second version of the app")
- end
-
- it "all_releases after rollback should have one entry" do
- expect(@fifth_deploy_all_releases.length).to eq(1)
- end
-
- it "all_releases after rollback should be the same as after the first deploy" do
- expect(@fifth_deploy_all_releases).to eq(@first_deploy_all_releases)
- end
- end
-
- describe "back to a previously deployed revision where resource rev == latest revision (explicit rollback)" do
- before do
- deploy_to_second_rev.run_action(:deploy)
- @first_deploy_all_releases = deploy_to_second_rev.provider_for_action(:deploy).all_releases
- deploy_to_previous_rev.run_action(:deploy)
- @second_deploy_all_releases = deploy_to_previous_rev.provider_for_action(:deploy).all_releases
- deploy_to_second_rev_again.run_action(:rollback)
- @third_deploy_all_releases = deploy_to_second_rev_again.provider_for_action(:deploy).all_releases
- deploy_to_latest_rev.run_action(:deploy)
- @fourth_deploy_all_releases = deploy_to_latest_rev.provider_for_action(:deploy).all_releases
- deploy_to_second_rev_again_again.run_action(:rollback)
- @fifth_deploy_all_releases = deploy_to_second_rev_again_again.provider_for_action(:deploy).all_releases
- end
-
- the_app_is_deployed_at_revision(:second_rev)
-
- it "restarts the application after rolling back" do
- expect(actual_operations_order).to eq(%w{deploy_to_second_rev deploy_to_previous_rev deploy_to_second_rev_again deploy_to_latest_rev deploy_to_second_rev_again_again})
- end
-
- it "is marked updated" do
- expect(deploy_to_second_rev_again_again).to be_updated_by_last_action
- end
-
- it "deploys the right code" do
- expect(IO.read(rel_path("current/app/app.rb"))).to include("this is the second version of the app")
- end
-
- it "all_releases after rollback should have one entry" do
- expect(@fifth_deploy_all_releases.length).to eq(1)
- end
-
- it "all_releases after rollback should be the same as after the first deploy" do
- expect(@fifth_deploy_all_releases).to eq(@first_deploy_all_releases)
- end
-
- end
-
- # CHEF-3435
- describe "to a deploy_to path that does not yet exist" do
-
- let(:top_level_tmpdir) { Dir.mktmpdir }
-
- # override top level deploy_directory let block with one that is two
- # directories deeper
- let(:deploy_directory) { File.expand_path("nested/deeper", top_level_tmpdir) }
-
- after do
- FileUtils.remove_entry_secure top_level_tmpdir
- end
-
- before do
- expect(File).not_to exist(deploy_directory)
- deploy_to_latest_rev.run_action(:deploy)
- end
-
- it "creates the required directory tree" do
- expect(File).to be_directory(rel_path("releases"))
- expect(File).to be_directory(rel_path("shared"))
- expect(File).to be_directory(rel_path("releases/#{latest_rev}"))
-
- expect(File).to be_directory(rel_path("current/tmp"))
- expect(File).to be_directory(rel_path("current/config"))
- expect(File).to be_directory(rel_path("current/public"))
-
- expect(File).to be_symlink(rel_path("current"))
- expect(File.readlink(rel_path("current"))).to eq(rel_path("releases/#{latest_rev}"))
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- end
- end
-
- context "when deploying an app with inline recipe callbacks" do
-
- # Use closures to capture and mutate this variable. This allows us to track
- # ordering of operations.
- callback_order = []
-
- let(:deploy_to_latest_with_inline_recipes) do
- deploy_to_latest_rev.dup.tap do |r|
- r.symlink_before_migrate "config/config.ru" => "config.ru"
- r.before_migrate do
- callback_order << :before_migrate
-
- file "#{release_path}/before_migrate.txt" do
- # The content here isn't relevant, but it gets printed when running
- # the tests. Could be handy for debugging.
- content callback_order.inspect
- end
- end
- r.before_symlink do
- callback_order << :before_symlink
-
- current_release_path = release_path
- ruby_block "ensure before symlink" do
- block do
- if ::File.exist?(::File.join(current_release_path, "/tmp"))
- raise "Ordering issue with provider, expected symlinks to not have been created"
- end
- end
- end
-
- file "#{release_path}/before_symlink.txt" do
- content callback_order.inspect
- end
- end
- r.before_restart do
- callback_order << :before_restart
-
- current_release_path = release_path
- ruby_block "ensure after symlink" do
- block do
- unless ::File.exist?(::File.join(current_release_path, "/tmp"))
- raise "Ordering issue with provider, expected symlinks to have been created"
- end
- end
- end
-
- file "#{release_path}/tmp/before_restart.txt" do
- content callback_order.inspect
- end
- end
- r.after_restart do
- callback_order << :after_restart
- file "#{release_path}/tmp/after_restart.txt" do
- content callback_order.inspect
- end
- end
- end
- end
-
- before do
- callback_order.clear # callback_order variable is global for this context group
- deploy_to_latest_with_inline_recipes.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:latest_rev)
-
- it "is marked updated" do
- expect(deploy_to_latest_with_inline_recipes).to be_updated_by_last_action
- end
-
- it "calls the callbacks in order" do
- expect(callback_order).to eq([:before_migrate, :before_symlink, :before_restart, :after_restart])
- end
-
- it "runs chef resources in the callbacks" do
- expect(File).to exist(rel_path("current/before_migrate.txt"))
- expect(File).to exist(rel_path("current/before_symlink.txt"))
- expect(File).to exist(rel_path("current/tmp/before_restart.txt"))
- expect(File).to exist(rel_path("current/tmp/after_restart.txt"))
- end
- end
-
- context "when deploying an app with in-repo callback scripts" do
- let(:deploy_with_in_repo_callbacks) do
- basic_deploy_resource.dup.tap do |r|
- r.repo git_bundle_with_in_repo_callbacks
- r.revision rev_with_in_repo_callbacks
- end
- end
-
- before do
- deploy_with_in_repo_callbacks.run_action(:deploy)
- end
-
- the_app_is_deployed_at_revision(:rev_with_in_repo_callbacks)
-
- it "runs chef resources in the callbacks" do
- expect(File).to exist(rel_path("current/before_migrate.txt"))
- expect(File).to exist(rel_path("current/before_symlink.txt"))
- expect(File).to exist(rel_path("current/tmp/before_restart.txt"))
- expect(File).to exist(rel_path("current/tmp/after_restart.txt"))
- end
-
- end
-
- context "when deploying an app with migrations" do
- let(:deploy_with_migration) do
- basic_deploy_resource.dup.tap do |r|
-
- # Need this so we can call methods from this test inside the inline
- # recipe callbacks
- spec_context = self
-
- r.revision latest_rev
-
- # enable migrations
- r.migrate true
- # abuse `shell_restart_command` so we can observe order of when the
- # miration command gets run
- r.migration_command shell_restart_command("migration")
- r.before_migrate do
-
- # inline recipe callbacks don't cwd, so you have to get the release
- # directory as a local and "capture" it in the closure.
- current_release = release_path
- execute spec_context.shell_restart_command("before_migrate") do
- cwd current_release
- end
- end
- r.before_symlink do
- current_release = release_path
- execute spec_context.shell_restart_command("before_symlink") do
- cwd current_release
- end
- end
-
- r.before_restart do
- current_release = release_path
- execute spec_context.shell_restart_command("before_restart") do
- cwd current_release
- end
- end
-
- r.after_restart do
- current_release = release_path
- execute spec_context.shell_restart_command("after_restart") do
- cwd current_release
- end
- end
-
- end
- end
-
- before do
- deploy_with_migration.run_action(:deploy)
- end
-
- it "runs migrations in between the before_migrate and before_symlink steps" do
- expect(actual_operations_order).to eq(%w{before_migrate migration before_symlink before_restart after_restart})
- end
- end
-
- context "when deploying an app with in-repo symlinks" do
- let(:deploy_with_in_repo_symlinks) do
- basic_deploy_resource.dup.tap do |r|
- r.repo git_bundle_with_in_repo_symlinks
- r.revision rev_with_in_repo_symlinks
- end
- end
-
- it "should not raise an exception calling File.utime on symlinks" do
- expect { deploy_with_in_repo_symlinks.run_action(:deploy) }.not_to raise_error
- end
- end
-
- context "when a previously deployed application has been nuked" do
-
- shared_examples_for "a redeployed application" do
-
- it "should redeploy the application" do
- expect(File).to be_directory(rel_path("releases"))
- expect(File).to be_directory(rel_path("shared"))
- expect(File).to be_directory(rel_path("releases/#{latest_rev}"))
-
- expect(File).to be_directory(rel_path("current/tmp"))
- expect(File).to be_directory(rel_path("current/config"))
- expect(File).to be_directory(rel_path("current/public"))
-
- expect(File).to be_symlink(rel_path("current"))
- expect(File.readlink(rel_path("current"))).to eq(rel_path("releases/#{latest_rev}"))
- end
- end
-
- # background: If a deployment is hosed and the user decides to rm -rf the
- # deployment dir, deploy resource should detect that and nullify its cache.
-
- context "by removing the entire deploy directory" do
-
- before do
- deploy_to_latest_rev.dup.run_action(:deploy)
- FileUtils.rm_rf(deploy_directory)
- deploy_to_latest_rev.dup.run_action(:deploy)
- end
-
- include_examples "a redeployed application"
-
- end
-
- context "by removing the current/ directory" do
-
- before do
- deploy_to_latest_rev.dup.run_action(:deploy)
- FileUtils.rm(rel_path("current"))
- deploy_to_latest_rev.dup.run_action(:deploy)
- end
-
- include_examples "a redeployed application"
-
- end
- end
-
- context "when a deployment fails" do
-
- shared_examples_for "a recovered deployment" do
-
- it "should redeploy the application" do
- expect(File).to be_directory(rel_path("releases"))
- expect(File).to be_directory(rel_path("shared"))
- expect(File).to be_directory(rel_path("releases/#{latest_rev}"))
-
- expect(File).to be_directory(rel_path("current/tmp"))
- expect(File).to be_directory(rel_path("current/config"))
- expect(File).to be_directory(rel_path("current/public"))
-
- expect(File).to be_symlink(rel_path("current"))
- expect(File.readlink(rel_path("current"))).to eq(rel_path("releases/#{latest_rev}"))
-
- # if callbacks ran, we know the app was deployed and not merely rolled
- # back to a (busted) prior deployment.
- expect(callback_order).to eq([:before_migrate,
- :before_symlink,
- :before_restart,
- :after_restart ])
- end
- end
-
- let!(:callback_order) { [] }
-
- let(:deploy_to_latest_with_callback_tracking) do
- resource = deploy_to_latest_rev.dup
- tracker = callback_order
- resource.before_migrate { tracker << :before_migrate }
- resource.before_symlink { tracker << :before_symlink }
- resource.before_restart { tracker << :before_restart }
- resource.after_restart { tracker << :after_restart }
- resource
- end
-
- [:before_migrate, :before_symlink, :before_restart, :after_restart].each do |callback|
-
- context "in the `#{callback}' callback" do
- before do
- expect { deploy_that_fails.run_action(:deploy) }.to raise_error(Exception, %r{I am a failed deploy})
- deploy_to_latest_with_callback_tracking.run_action(:deploy)
- end
-
- let(:deploy_that_fails) do
- resource = deploy_to_latest_rev.dup
- errant_callback = lambda { |x| raise Exception, "I am a failed deploy" }
- resource.send(callback, &errant_callback)
- resource
- end
-
- include_examples "a recovered deployment"
-
- end
-
- end
-
- context "in the service restart step" do
-
- let(:deploy_that_fails) do
- resource = deploy_to_latest_rev.dup
- resource.restart_command("RUBYOPT=\"\" ruby -e 'exit 1'")
- resource
- end
-
- before do
- expect { deploy_that_fails.run_action(:deploy) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed)
- deploy_to_latest_with_callback_tracking.run_action(:deploy)
- end
-
- include_examples "a recovered deployment"
- end
-
- context "when cloning the app code" do
-
- class BadTimeScmProvider
- def initialize(new_resource, run_context)
- end
-
- def load_current_resource
- end
-
- def revision_slug
- "5"
- end
-
- def run_action(action)
- raise "network error"
- end
- end
-
- let(:deploy_that_fails) do
- resource = deploy_to_latest_rev.dup
- resource.scm_provider(BadTimeScmProvider)
- resource
- end
-
- before do
- expect { deploy_that_fails.run_action(:deploy) }.to raise_error(RuntimeError, /network error/)
- deploy_to_latest_with_callback_tracking.run_action(:deploy)
- end
-
- include_examples "a recovered deployment"
- end
-
- context "and then is deployed to a different revision" do
-
- let(:deploy_that_fails) do
- resource = deploy_to_previous_rev.dup
- resource.after_restart { |x| raise Exception, "I am a failed deploy" }
- resource
- end
-
- before do
- expect { deploy_that_fails.run_action(:deploy) }.to raise_error(Exception, %r{I am a failed deploy})
- deploy_to_latest_rev.run_action(:deploy)
- end
-
- it "removes the unsuccessful deploy after a later successful deploy" do
- expect(::File).not_to exist(File.join(deploy_directory, "releases", previous_rev))
- end
-
- end
-
- end
-end
diff --git a/spec/functional/resource/ifconfig_spec.rb b/spec/functional/resource/ifconfig_spec.rb
index 0298dbcf45..fbb8995d52 100644
--- a/spec/functional/resource/ifconfig_spec.rb
+++ b/spec/functional/resource/ifconfig_spec.rb
@@ -20,7 +20,7 @@ require "functional/resource/base"
require "chef/mixin/shell_out"
# run this test only for following platforms.
-include_flag = !(%w{ubuntu centos aix}.include?(ohai[:platform]))
+include_flag = !(%w{amazon debian aix}.include?(ohai[:platform_family]) || (ohai[:platform_family] == "rhel" && ohai[:platform_version].to_i < 7))
describe Chef::Resource::Ifconfig, :requires_root, :skip_travis, :external => include_flag do
# This test does not work in travis because there is no eth0
diff --git a/spec/functional/resource/mount_spec.rb b/spec/functional/resource/mount_spec.rb
index c756b0d3d4..c98d6cec25 100644
--- a/spec/functional/resource/mount_spec.rb
+++ b/spec/functional/resource/mount_spec.rb
@@ -22,7 +22,7 @@ require "chef/mixin/shell_out"
require "tmpdir"
# run this test only for following platforms.
-include_flag = !(%w{ubuntu centos aix solaris2}.include?(ohai[:platform]))
+include_flag = !(%w{debian rhel amazon aix solaris2}.include?(ohai[:platform_family]))
describe Chef::Resource::Mount, :requires_root, :skip_travis, :external => include_flag do
# Disabled in travis because it refuses to let us mount a ramdisk. /dev/ramX does not
@@ -35,15 +35,19 @@ describe Chef::Resource::Mount, :requires_root, :skip_travis, :external => inclu
def setup_device_for_mount
# use ramdisk for creating a test device for mount.
# This can cleaner if we have chef resource/provider for ramdisk.
- case ohai[:platform]
+ case ohai[:platform_family]
when "aix"
# On AIX, we can't create a ramdisk inside a WPAR, so we use
# a "namefs" mount against / to test
# https://www-304.ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.performance/namefs_file_sys.htm
device = "/"
fstype = "namefs"
- when "ubuntu", "centos"
+ when "debian", "rhel", "amazon"
device = "/dev/ram1"
+ unless File.exist?(device)
+ shell_out("mknod -m 660 #{device} b 1 0")
+ shell_out("chown root:disk #{device}")
+ end
shell_out("ls -1 /dev/ram*").stdout.each_line do |d|
if shell_out("mount | grep #{d}").exitstatus == "1"
# this device is not mounted, so use it.
diff --git a/spec/functional/resource/registry_spec.rb b/spec/functional/resource/registry_spec.rb
index b6767d47a3..7318086034 100644
--- a/spec/functional/resource/registry_spec.rb
+++ b/spec/functional/resource/registry_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Prajakta Purohit (<prajakta@chef.io>)
# Author:: Lamont Granquist (<lamont@chef.io>)
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -244,7 +244,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do
@new_resource.recursive(true)
@new_resource.run_action(:create)
- @new_resource.values.each do |value|
+ @new_resource.each_value do |value|
expect(@registry.value_exists?(reg_child, value)).to eq(true)
end
end
@@ -430,7 +430,7 @@ describe Chef::Resource::RegistryKey, :windows_only, :broken => true do
@new_resource.recursive(true)
@new_resource.run_action(:create_if_missing)
- @new_resource.values.each do |value|
+ @new_resource.each_value do |value|
expect(@registry.value_exists?(reg_child + '\Adipose', value)).to eq(true)
end
end
diff --git a/spec/functional/resource/remote_file_spec.rb b/spec/functional/resource/remote_file_spec.rb
index 94c42a73ba..8e484b2968 100644
--- a/spec/functional/resource/remote_file_spec.rb
+++ b/spec/functional/resource/remote_file_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Seth Chisamore (<schisamo@chef.io>)
-# Copyright:: Copyright 2011-2016, Chef Software Inc.
+# Copyright:: Copyright 2011-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,6 +28,9 @@ describe Chef::Resource::RemoteFile do
before(:each) do
@old_file_cache = Chef::Config[:file_cache_path]
Chef::Config[:file_cache_path] = file_cache_path
+ Chef::Config[:rest_timeout] = 2
+ Chef::Config[:http_retry_delay] = 0
+ Chef::Config[:http_retry_count] = 0
end
after(:each) do
@@ -55,11 +58,11 @@ describe Chef::Resource::RemoteFile do
let(:default_mode) { (0666 & ~File.umask).to_s(8) }
context "when fetching files over HTTP" do
- before(:each) do
- start_tiny_server
+ before(:all) do
+ start_tiny_server(RequestTimeout: 1)
end
- after(:each) do
+ after(:all) do
stop_tiny_server
end
@@ -97,21 +100,22 @@ describe Chef::Resource::RemoteFile do
context "when fetching files over HTTPS" do
- before(:each) do
+ before(:all) do
cert_text = File.read(File.expand_path("ssl/chef-rspec.cert", CHEF_SPEC_DATA))
cert = OpenSSL::X509::Certificate.new(cert_text)
key_text = File.read(File.expand_path("ssl/chef-rspec.key", CHEF_SPEC_DATA))
key = OpenSSL::PKey::RSA.new(key_text)
- server_opts = { :SSLEnable => true,
- :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE,
- :SSLCertificate => cert,
- :SSLPrivateKey => key }
+ server_opts = { SSLEnable: true,
+ SSLVerifyClient: OpenSSL::SSL::VERIFY_NONE,
+ SSLCertificate: cert,
+ SSLPrivateKey: key,
+ RequestTimeout: 1 }
start_tiny_server(server_opts)
end
- after(:each) do
+ after(:all) do
stop_tiny_server
end
@@ -295,11 +299,11 @@ describe Chef::Resource::RemoteFile do
end
context "when dealing with content length checking" do
- before(:each) do
- start_tiny_server
+ before(:all) do
+ start_tiny_server(RequestTimeout: 1)
end
- after(:each) do
+ after(:all) do
stop_tiny_server
end
diff --git a/spec/functional/resource/user/useradd_spec.rb b/spec/functional/resource/user/useradd_spec.rb
index e783356c9f..175809b5c0 100644
--- a/spec/functional/resource/user/useradd_spec.rb
+++ b/spec/functional/resource/user/useradd_spec.rb
@@ -646,10 +646,10 @@ describe Chef::Provider::User::Useradd, metadata do
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.
+ (Chef::VersionConstraint.new("~> 6.8").include?(OHAI_SYSTEM["platform_version"].to_f) || Chef::VersionConstraint.new("~> 7.3").include?(OHAI_SYSTEM["platform_version"].to_f))
+ # RHEL 6.8 and 7.3 ship with a fixed `usermod` command
+ # Reference: https://access.redhat.com/errata/RHBA-2016:0864
+ # Reference: https://access.redhat.com/errata/RHBA-2016:2322
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")
diff --git a/spec/functional/resource/windows_task_spec.rb b/spec/functional/resource/windows_task_spec.rb
index fbb5e4dd12..2839b12288 100644
--- a/spec/functional/resource/windows_task_spec.rb
+++ b/spec/functional/resource/windows_task_spec.rb
@@ -31,20 +31,30 @@ describe Chef::Resource::WindowsTask, :windows_only do
describe "action :create" do
after { delete_task }
-
context "when frequency and frequency_modifier are not passed" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
new_resource.command task_name
+ # Make sure MM/DD/YYYY is accepted
+ new_resource.start_day "09/20/2017"
new_resource
end
- it "creates a scheduled task to run every 1 hr" do
+ it "creates a scheduled task to run every 1 hr starting on 09/20/2017" do
subject.run_action(:create)
task_details = windows_task_provider.send(:load_task_hash, task_name)
expect(task_details[:TaskName]).to eq("\\chef-client")
expect(task_details[:TaskToRun]).to eq("chef-client")
expect(task_details[:"Repeat:Every"]).to eq("1 Hour(s), 0 Minute(s)")
+
+ # This test will not work across locales
+ expect(task_details[:StartDate]).to eq("9/20/2017")
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
end
end
@@ -66,6 +76,12 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:"Repeat:Every"]).to eq("0 Hour(s), 15 Minute(s)")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
context "frequency :hourly" do
@@ -86,6 +102,12 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:"Repeat:Every"]).to eq("3 Hour(s), 0 Minute(s)")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
context "frequency :daily" do
@@ -106,6 +128,12 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:Days]).to eq("Every 1 day(s)")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
context "frequency :monthly" do
@@ -127,6 +155,13 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:Months]).to eq("FEB, APR, JUN, AUG, OCT, DEC")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ skip "This functionality needs to be handle"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
context "frequency :once" do
@@ -155,6 +190,73 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:StartTime]).to eq("5:00:00 PM")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.start_time "17:00"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+ end
+
+ context "frequency :none" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :none
+ new_resource
+ end
+
+ it "creates the scheduled task to run on demand only" do
+ subject.run_action(:create)
+ task_details = windows_task_provider.send(:load_task_hash, task_name)
+
+ expect(task_details[:TaskName]).to eq("\\chef-client")
+ expect(task_details[:TaskToRun]).to eq("chef-client")
+ expect(task_details[:ScheduleType]).to eq("On demand only")
+ expect(task_details[:StartTime]).to eq("N/A")
+ expect(task_details[:StartDate]).to eq("N/A")
+ expect(task_details[:NextRunTime]).to eq("N/A")
+ expect(task_details[:none]).to eq(true)
+ expect(task_details[:run_level]).to eq("HighestAvailable")
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "frequency :onstart" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :onstart
+ new_resource
+ end
+
+ it "creates the scheduled task to run at system start up" do
+ subject.run_action(:create)
+ task_details = windows_task_provider.send(:load_task_hash, task_name)
+
+ expect(task_details[:TaskName]).to eq("\\chef-client")
+ expect(task_details[:TaskToRun]).to eq("chef-client")
+ expect(task_details[:ScheduleType]).to eq("At system start up")
+ expect(task_details[:StartTime]).to eq("N/A")
+ expect(task_details[:StartDate]).to eq("N/A")
+ expect(task_details[:NextRunTime]).to eq("N/A")
+ expect(task_details[:onstart]).to eq(true)
+ expect(task_details[:run_level]).to eq("HighestAvailable")
+ end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
end
end
@@ -177,6 +279,13 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+ it "does not converge the resource if it is already converged" do
+ skip "This functionality needs to be handle"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
context "when days are provided" do
it "creates the scheduled task to run on particular days" do
subject.day "Mon, Fri"
@@ -190,6 +299,14 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:Months]).to eq("Every 2 week(s)")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.day "Mon, Fri"
+ subject.frequency_modifier 2
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
context "when invalid day is passed" do
@@ -224,6 +341,12 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:ScheduleType]).to eq("At logon time")
expect(task_details[:run_level]).to eq("HighestAvailable")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
context "frequency :on_idle" do
@@ -252,6 +375,13 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:run_level]).to eq("HighestAvailable")
expect(task_details[:idle_time]).to eq("PT20M")
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.idle_time 20
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
end
@@ -275,10 +405,18 @@ describe Chef::Resource::WindowsTask, :windows_only do
expect(task_details[:random_delay]).to eq("PT20M")
end
+ it "does not converge the resource if it is already converged" do
+ subject.frequency :minute
+ subject.random_delay "PT20M"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
it "raises error if invalid random_delay is passed" do
subject.frequency :minute
subject.random_delay "abc"
- expect { subject.after_created }.to raise_error("Invalid value passed for `random_delay`. Please pass seconds as a String e.g. '60'.")
+ expect { subject.after_created }.to raise_error("Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
end
it "raises error if random_delay is passed with frequency on_idle" do
@@ -289,6 +427,192 @@ describe Chef::Resource::WindowsTask, :windows_only do
end
end
+ describe "Examples of idempotent checks for each frequency" do
+ after { delete_task }
+ context "For frequency :once" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :once
+ new_resource.start_time "17:00"
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier as 1" do
+ subject.frequency_modifier 1
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "create task by adding frequency_modifier as 5" do
+ skip "This functionality needs to be handle"
+ subject.frequency_modifier 5
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :none" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :none
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier as 1" do
+ subject.frequency_modifier 1
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "create task by adding frequency_modifier as 5" do
+ skip "This functionality needs to be handle"
+ subject.frequency_modifier 5
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :weekly" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :weekly
+ new_resource
+ end
+
+ it "create task by adding start_day" do
+ skip "This functionality needs to be handle"
+ subject.start_day "12/28/2018"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "create task by adding frequency_modifier and random_delay" do
+ skip "This functionality needs to be handle"
+ subject.frequency_modifier 3
+ subject.random_delay "60"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :monthly" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :once
+ new_resource.start_time "17:00"
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier as 1" do
+ subject.frequency_modifier 1
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "create task by adding frequency_modifier as 5" do
+ skip "This functionality needs to be handle"
+ subject.frequency_modifier 5
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :hourly" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :hourly
+ new_resource.frequency_modifier 5
+ new_resource.random_delay "2400"
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier and random_delay" do
+ skip "This functionality needs to be handle"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :daily" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :daily
+ new_resource.frequency_modifier 2
+ new_resource.random_delay "2400"
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier and random_delay" do
+ skip "This functionality needs to be handle"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :on_logon" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.frequency :on_logon
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier and random_delay" do
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+
+ it "create task by adding frequency_modifier as 5" do
+ skip "This functionality needs to be handle"
+ subject.frequency_modifier 5
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+
+ context "For frequency :onstart" do
+ subject do
+ new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
+ new_resource.command task_name
+ new_resource.run_level :highest
+ new_resource.frequency :onstart
+ new_resource.frequency_modifier 20
+ new_resource
+ end
+
+ it "create task by adding frequency_modifier as 20" do
+ skip "This functionality needs to be handle"
+ subject.run_action(:create)
+ subject.run_action(:create)
+ expect(subject).not_to be_updated_by_last_action
+ end
+ end
+ end
+
describe "#after_created" do
subject do
new_resource = Chef::Resource::WindowsTask.new(task_name, run_context)
@@ -300,7 +624,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
context "when start_day is passed with frequency :onstart" do
it "raises error" do
subject.frequency :onstart
- subject.start_day "mon"
+ subject.start_day "09/20/2017"
expect { subject.after_created }.to raise_error("`start_day` property is not supported with frequency: onstart")
end
end
@@ -309,7 +633,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
it "raises error" do
subject.user "Administrator"
subject.frequency :onstart
- expect { subject.after_created }.to raise_error("Can't specify a non-system user without a password!")
+ expect { subject.after_created }.to raise_error(%q{Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: 'NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', 'USERS'})
end
end
@@ -325,7 +649,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
it "raises error" do
subject.frequency_modifier 1450
subject.frequency :minute
- expect { subject.after_created }.to raise_error("frequency_modifier value 1450 is invalid. Valid values for :minute frequency are 1 - 1439.")
+ expect { subject.after_created }.to raise_error("frequency_modifier value 1450 is invalid. Valid values for :minute frequency are 1 - 1439.")
end
end
@@ -333,7 +657,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
it "raises error" do
subject.months "xyz"
subject.frequency :monthly
- expect { subject.after_created }.to raise_error("months attribute invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
+ expect { subject.after_created }.to raise_error("months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
end
end
@@ -341,7 +665,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
it "raises error" do
subject.idle_time 1000
subject.frequency :on_idle
- expect { subject.after_created }.to raise_error("idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ expect { subject.after_created }.to raise_error("idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
end
end
@@ -349,7 +673,7 @@ describe Chef::Resource::WindowsTask, :windows_only do
it "raises error" do
subject.idle_time 300
subject.frequency :monthly
- expect { subject.after_created }.to raise_error("idle_time attribute is only valid for tasks that run on_idle")
+ expect { subject.after_created }.to raise_error("idle_time property is only valid for tasks that run on_idle")
end
end
end
@@ -367,6 +691,13 @@ describe Chef::Resource::WindowsTask, :windows_only do
task_details = windows_task_provider.send(:load_task_hash, task_name)
expect(task_details).to eq(false)
end
+
+ it "does not converge the resource if it is already converged" do
+ subject.run_action(:create)
+ subject.run_action(:delete)
+ subject.run_action(:delete)
+ expect(subject).not_to be_updated_by_last_action
+ end
end
describe "action :run" do
diff --git a/spec/functional/win32/security_spec.rb b/spec/functional/win32/security_spec.rb
index 40ae99bfa4..6c24cbec08 100644
--- a/spec/functional/win32/security_spec.rb
+++ b/spec/functional/win32/security_spec.rb
@@ -17,6 +17,8 @@
#
require "spec_helper"
+require "mixlib/shellout"
+require "chef/mixin/user_context"
if Chef::Platform.windows?
require "chef/win32/security"
end
@@ -26,13 +28,37 @@ describe "Chef::Win32::Security", :windows_only do
expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to eq(true)
end
- # We've done some investigation adding a negative test and it turned
- # out to be a lot of work since mixlib-shellout doesn't have user
- # support for windows.
- #
- # TODO - Add negative tests once mixlib-shellout has user support
- it "has_admin_privileges? returns false when running as non-admin" do
- skip "requires user support in mixlib-shellout"
+ describe "running as non admin user" do
+ include Chef::Mixin::UserContext
+ let(:user) { "security_user" }
+ let(:password) { "Security@123" }
+
+ let(:domain) do
+ whoami = Mixlib::ShellOut.new("whoami")
+ whoami.run_command
+ whoami.error!
+ whoami.stdout.split("\\")[0]
+ end
+
+ before do
+ allow_any_instance_of(Chef::Mixin::UserContext).to receive(:node).and_return({ "platform_family" => "windows" })
+ allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false)
+ add_user = Mixlib::ShellOut.new("net user #{user} #{password} /ADD")
+ add_user.run_command
+ add_user.error!
+ end
+
+ after do
+ delete_user = Mixlib::ShellOut.new("net user #{user} /delete")
+ delete_user.run_command
+ delete_user.error!
+ end
+ it "has_admin_privileges? returns false" do
+ has_admin_privileges = with_user_context(user, password, domain, :local) do
+ Chef::ReservedNames::Win32::Security.has_admin_privileges?
+ end
+ expect(has_admin_privileges).to eq(false)
+ end
end
describe "get_file_security" do
@@ -97,4 +123,31 @@ describe "Chef::Win32::Security", :windows_only do
end
end
end
+
+ describe ".get_token_information_elevation_type" do
+ let(:token_rights) { Chef::ReservedNames::Win32::Security::TOKEN_READ }
+
+ let(:token) do
+ Chef::ReservedNames::Win32::Security.open_process_token(
+ Chef::ReservedNames::Win32::Process.get_current_process,
+ token_rights)
+ end
+
+ context "when the token is valid" do
+ let(:token_elevation_type) { [:TokenElevationTypeDefault, :TokenElevationTypeFull, :TokenElevationTypeLimited] }
+
+ it "returns the token elevation type" do
+ elevation_type = Chef::ReservedNames::Win32::Security.get_token_information_elevation_type(token)
+ expect(token_elevation_type).to include(elevation_type)
+ end
+ end
+
+ context "when the token is invalid" do
+ it "raises `handle invalid` error" do
+ # If `OpenProcessToken` is stubbed, `open_process_token` returns an invalid token
+ allow(Chef::ReservedNames::Win32::Security).to receive(:OpenProcessToken).and_return(true)
+ expect { Chef::ReservedNames::Win32::Security.get_token_information_elevation_type(token) }.to raise_error(Chef::Exceptions::Win32APIError)
+ end
+ end
+ end
end
diff --git a/spec/integration/knife/data_bag_show_spec.rb b/spec/integration/knife/data_bag_show_spec.rb
index 22381adb9e..38dfd8730d 100644
--- a/spec/integration/knife/data_bag_show_spec.rb
+++ b/spec/integration/knife/data_bag_show_spec.rb
@@ -44,7 +44,7 @@ EOM
end
it "with a single item" do
- knife("data bag show rocket falcon9").should_succeed <<EOM, stderr: "WARNING: Unencrypted data bag detected, ignoring any provided secret options.\n"
+ knife("data bag show rocket falcon9").should_succeed <<EOM
heavy: true
id: falcon9
EOM
diff --git a/spec/integration/knife/deps_spec.rb b/spec/integration/knife/deps_spec.rb
index 40ec411780..3f200396ba 100644
--- a/spec/integration/knife/deps_spec.rb
+++ b/spec/integration/knife/deps_spec.rb
@@ -242,7 +242,7 @@ EOM
it "knife deps --tree prints each once" do
knife("deps --tree /roles/foo.json /roles/self.json") do
expect(stdout).to eq("/roles/foo.json\n /roles/bar.json\n /roles/baz.json\n /roles/foo.json\n/roles/self.json\n /roles/self.json\n")
- expect(stderr).to eq("WARNING: No knife configuration file found\n")
+ expect(stderr).to eq("WARNING: No knife configuration file found. See https://docs.chef.io/config_rb_knife.html for details.\n")
end
end
end
@@ -580,7 +580,7 @@ EOM
it "knife deps --tree prints each once" do
knife("deps --remote --tree /roles/foo.json /roles/self.json") do
expect(stdout).to eq("/roles/foo.json\n /roles/bar.json\n /roles/baz.json\n /roles/foo.json\n/roles/self.json\n /roles/self.json\n")
- expect(stderr).to eq("WARNING: No knife configuration file found\n")
+ expect(stderr).to eq("WARNING: No knife configuration file found. See https://docs.chef.io/config_rb_knife.html for details.\n")
end
end
end
diff --git a/spec/integration/recipes/noop_resource_spec.rb b/spec/integration/recipes/noop_resource_spec.rb
index e0cf47c371..db6b668553 100644
--- a/spec/integration/recipes/noop_resource_spec.rb
+++ b/spec/integration/recipes/noop_resource_spec.rb
@@ -4,7 +4,7 @@ describe "Resources with a no-op provider" do
include IntegrationSupport
context "with noop provider providing foo" do
- before(:context) do
+ before(:each) do
class NoOpFoo < Chef::Resource
resource_name "hi_there"
default_action :update
diff --git a/spec/integration/recipes/recipe_dsl_spec.rb b/spec/integration/recipes/recipe_dsl_spec.rb
index f7a0e8b6e8..0250786f0e 100644
--- a/spec/integration/recipes/recipe_dsl_spec.rb
+++ b/spec/integration/recipes/recipe_dsl_spec.rb
@@ -12,7 +12,7 @@ describe "Recipe DSL methods" do
before { Namer.current_index += 1 }
context "with resource 'base_thingy' declared as BaseThingy" do
- before(:context) do
+ before(:each) do
class BaseThingy < Chef::Resource
resource_name "base_thingy"
@@ -66,7 +66,7 @@ describe "Recipe DSL methods" do
end
context "nameless resources" do
- before(:context) do
+ before(:each) do
class NamelessThingy < BaseThingy
resource_name :nameless_thingy
provides :nameless_thingy
@@ -91,7 +91,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named RecipeDSLSpecNamespace::Bar::BarThingy" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Bar::BarThingy < BaseThingy
end
@@ -106,7 +106,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named Chef::Resource::NoNameThingy with resource_name nil" do
- before(:context) do
+ before(:each) do
class Chef::Resource::NoNameThingy < BaseThingy
resource_name nil
@@ -122,7 +122,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named AnotherNoNameThingy with resource_name :another_thingy_name" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy < BaseThingy
resource_name :another_thingy_name
@@ -146,7 +146,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named AnotherNoNameThingy2 with resource_name :another_thingy_name2; resource_name :another_thingy_name3" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy2 < BaseThingy
resource_name :another_thingy_name2
@@ -178,7 +178,7 @@ describe "Recipe DSL methods" do
context "provides overriding resource_name" do
context "with a resource named AnotherNoNameThingy3 with provides :another_no_name_thingy3, os: 'blarghle'" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy3 < BaseThingy
resource_name :another_no_name_thingy_3
@@ -207,7 +207,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named AnotherNoNameThingy4 with two provides" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy4 < BaseThingy
resource_name :another_no_name_thingy_4
@@ -247,7 +247,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named AnotherNoNameThingy5, a different resource_name, and a provides with the original resource_name" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy5 < BaseThingy
resource_name :another_thingy_name_for_another_no_name_thingy5
@@ -284,7 +284,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named AnotherNoNameThingy6, a provides with the original resource name, and a different resource_name" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy6 < BaseThingy
provides :another_no_name_thingy6, os: "blarghle"
@@ -321,7 +321,7 @@ describe "Recipe DSL methods" do
end
context "with a resource named AnotherNoNameThingy7, a new resource_name, and provides with that new resource name" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy7 < BaseThingy
resource_name :another_thingy_name_for_another_no_name_thingy7
@@ -359,7 +359,7 @@ describe "Recipe DSL methods" do
# opposite order from the previous test (provides, then resource_name)
context "with a resource named AnotherNoNameThingy8, a provides with a new resource name, and resource_name with that new resource name" do
- before(:context) do
+ before(:each) do
class AnotherNoNameThingy8 < BaseThingy
provides :another_thingy_name_for_another_no_name_thingy8, os: "blarghle"
@@ -399,7 +399,7 @@ describe "Recipe DSL methods" do
context "provides" do
context "when MySupplier provides :hemlock" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::MySupplier < BaseThingy
resource_name :hemlock
@@ -422,7 +422,7 @@ describe "Recipe DSL methods" do
end
context "when Thingy3 has resource_name :thingy3" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy3 < BaseThingy
resource_name :thingy3
@@ -438,7 +438,7 @@ describe "Recipe DSL methods" do
end
context "and Thingy4 has resource_name :thingy3" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy4 < BaseThingy
resource_name :thingy3
@@ -446,11 +446,11 @@ describe "Recipe DSL methods" do
end
- it "thingy3 works in a recipe and yields Thingy3 (the alphabetical one)" do
+ it "thingy3 works in a recipe and yields Thingy4 (the last one)" do
recipe = converge do
thingy3("blah") {}
end
- expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy3
+ expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy4
end
it "thingy4 does not work in a recipe" do
@@ -460,13 +460,13 @@ describe "Recipe DSL methods" do
end
it "resource_matching_short_name returns Thingy4" do
- expect(Chef::Resource.resource_matching_short_name(:thingy3)).to eq RecipeDSLSpecNamespace::Thingy3
+ expect(Chef::Resource.resource_matching_short_name(:thingy3)).to eq RecipeDSLSpecNamespace::Thingy4
end
end
end
context "when Thingy5 has resource_name :thingy5 and provides :thingy5reverse, :thingy5_2 and :thingy5_2reverse" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy5 < BaseThingy
resource_name :thingy5
@@ -485,7 +485,7 @@ describe "Recipe DSL methods" do
end
context "and Thingy6 provides :thingy5" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy6 < BaseThingy
resource_name :thingy6
@@ -501,19 +501,19 @@ describe "Recipe DSL methods" do
expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy6
end
- it "thingy5 works in a recipe and yields Foo::Thingy5 (the alphabetical one)" do
+ it "thingy5 works in a recipe and yields Foo::Thingy6 (the last one)" do
recipe = converge do
thingy5("blah") {}
end
- expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy5
+ expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy6
end
- it "resource_matching_short_name returns Thingy5" do
+ it "resource_matching_short_name returns Thingy6" do
expect(Chef::Resource.resource_matching_short_name(:thingy5)).to eq RecipeDSLSpecNamespace::Thingy5
end
context "and AThingy5 provides :thingy5reverse" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::AThingy5 < BaseThingy
resource_name :thingy5reverse
@@ -530,7 +530,7 @@ describe "Recipe DSL methods" do
end
context "and ZRecipeDSLSpecNamespace::Thingy5 provides :thingy5_2" do
- before(:context) do
+ before(:each) do
module ZRecipeDSLSpecNamespace
class Thingy5 < BaseThingy
@@ -540,16 +540,16 @@ describe "Recipe DSL methods" do
end
- it "thingy5_2 works in a recipe and yields the RecipeDSLSpaceNamespace one (the alphabetical one)" do
+ it "thingy5_2 works in a recipe and yields the ZRecipeDSLSpaceNamespace one (the last one)" do
recipe = converge do
thingy5_2("blah") {}
end
- expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy5
+ expect(BaseThingy.created_resource).to eq ZRecipeDSLSpecNamespace::Thingy5
end
end
context "and ARecipeDSLSpecNamespace::Thingy5 provides :thingy5_2" do
- before(:context) do
+ before(:each) do
module ARecipeDSLSpecNamespace
class Thingy5 < BaseThingy
@@ -569,7 +569,7 @@ describe "Recipe DSL methods" do
end
context "when Thingy3 has resource_name :thingy3" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy3 < BaseThingy
resource_name :thingy3
@@ -585,7 +585,7 @@ describe "Recipe DSL methods" do
end
context "and Thingy4 has resource_name :thingy3" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy4 < BaseThingy
resource_name :thingy3
@@ -593,11 +593,11 @@ describe "Recipe DSL methods" do
end
- it "thingy3 works in a recipe and yields Thingy3 (the alphabetical one)" do
+ it "thingy3 works in a recipe and yields Thingy4 (the last one)" do
recipe = converge do
thingy3("blah") {}
end
- expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy3
+ expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy4
end
it "thingy4 does not work in a recipe" do
@@ -607,12 +607,12 @@ describe "Recipe DSL methods" do
end
it "resource_matching_short_name returns Thingy4" do
- expect(Chef::Resource.resource_matching_short_name(:thingy3)).to eq RecipeDSLSpecNamespace::Thingy3
+ expect(Chef::Resource.resource_matching_short_name(:thingy3)).to eq RecipeDSLSpecNamespace::Thingy4
end
end
context "and Thingy4 has resource_name :thingy3" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy4 < BaseThingy
resource_name :thingy3
@@ -620,11 +620,11 @@ describe "Recipe DSL methods" do
end
- it "thingy3 works in a recipe and yields Thingy3 (the alphabetical one)" do
+ it "thingy3 works in a recipe and yields Thingy4 (the last one)" do
recipe = converge do
thingy3("blah") {}
end
- expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy3
+ expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy4
end
it "thingy4 does not work in a recipe" do
@@ -634,7 +634,7 @@ describe "Recipe DSL methods" do
end
it "resource_matching_short_name returns Thingy4" do
- expect(Chef::Resource.resource_matching_short_name(:thingy3)).to eq RecipeDSLSpecNamespace::Thingy3
+ expect(Chef::Resource.resource_matching_short_name(:thingy3)).to eq RecipeDSLSpecNamespace::Thingy4
end
end
end
@@ -642,7 +642,7 @@ describe "Recipe DSL methods" do
end
context "when Thingy7 provides :thingy8" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy7 < BaseThingy
resource_name :thingy7
@@ -652,7 +652,7 @@ describe "Recipe DSL methods" do
end
context "and Thingy8 has resource_name :thingy8" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy8 < BaseThingy
resource_name :thingy8
@@ -667,11 +667,11 @@ describe "Recipe DSL methods" do
expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy7
end
- it "thingy8 works in a recipe and yields Thingy7 (alphabetical)" do
+ it "thingy8 works in a recipe and yields Thingy7 (last)" do
recipe = converge do
thingy8("blah") {}
end
- expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy7
+ expect(BaseThingy.created_resource).to eq RecipeDSLSpecNamespace::Thingy8
end
it "resource_matching_short_name returns Thingy8" do
@@ -681,7 +681,7 @@ describe "Recipe DSL methods" do
end
context "when Thingy12 provides :thingy12, :twizzle and :twizzle2" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy12 < BaseThingy
resource_name :thingy12
@@ -714,7 +714,7 @@ describe "Recipe DSL methods" do
end
context "with platform-specific resources 'my_super_thingy_foo' and 'my_super_thingy_bar'" do
- before(:context) do
+ before(:each) do
class MySuperThingyFoo < BaseThingy
resource_name :my_super_thingy_foo
provides :my_super_thingy, platform: "foo"
@@ -760,7 +760,7 @@ describe "Recipe DSL methods" do
end
context "when Thingy10 provides :thingy10" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy10 < BaseThingy
resource_name :thingy10
end
@@ -775,7 +775,7 @@ describe "Recipe DSL methods" do
end
context "when Thingy11 provides :thingy11" do
- before(:context) do
+ before(:each) do
class RecipeDSLSpecNamespace::Thingy11 < BaseThingy
resource_name :thingy10
end
@@ -853,17 +853,17 @@ describe "Recipe DSL methods" do
end
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
+ it "two_classes_one_dsl resolves to Z (last)" do
temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
- expect(BaseThingy.created_resource).to eq resource_class
+ expect(BaseThingy.created_resource).to eq resource_class_z
end
- it "resource_matching_short_name returns B" do
- expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ it "resource_matching_short_name returns Z" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class_z
end
context "and a priority array [ Z, B ]" do
@@ -880,8 +880,8 @@ describe "Recipe DSL methods" do
expect(BaseThingy.created_resource).to eq resource_class_z
end
- it "resource_matching_short_name returns B" do
- expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ it "resource_matching_short_name returns Z" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class_z
end
context "when Z provides(:two_classes_one_dsl) { false }" do
@@ -919,8 +919,8 @@ describe "Recipe DSL methods" do
expect(BaseThingy.created_resource).to eq resource_class_z
end
- it "resource_matching_short_name returns B" do
- expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class
+ it "resource_matching_short_name returns Z" do
+ expect(Chef::Resource.resource_matching_short_name(two_classes_one_dsl)).to eq resource_class_z
end
context "when Z provides(:two_classes_one_dsl) { false }" do
@@ -1047,13 +1047,13 @@ describe "Recipe DSL methods" do
context "which provides :two_classes_one_dsl" do
before { provider_class_z.provides two_classes_one_dsl }
- it "two_classes_one_dsl resolves to B (alphabetically earliest)" do
+ it "two_classes_one_dsl resolves to Z (last)" do
temp_two_classes_one_dsl = two_classes_one_dsl
recipe = converge do
instance_eval("#{temp_two_classes_one_dsl} 'blah'")
end
expect(recipe.logged_warnings).to eq ""
- expect(BaseThingy.created_provider).to eq provider_class
+ expect(BaseThingy.created_provider).to eq provider_class_z
end
context "with a priority array [ Z, B ]" do
@@ -1309,7 +1309,7 @@ describe "Recipe DSL methods" do
end
context "with UTF-8 provides" do
- before(:context) do
+ before(:each) do
class UTF8Thingy < BaseThingy
resource_name :Straße
provides :Straße
diff --git a/spec/integration/recipes/resource_action_spec.rb b/spec/integration/recipes/resource_action_spec.rb
index f5f2d4a764..d6ea4347c4 100644
--- a/spec/integration/recipes/resource_action_spec.rb
+++ b/spec/integration/recipes/resource_action_spec.rb
@@ -1,5 +1,30 @@
require "support/shared/integration/integration_helper"
+class NoActionJackson < Chef::Resource
+ use_automatic_resource_name
+
+ def foo(value = nil)
+ @foo = value if value
+ @foo
+ end
+
+ class <<self
+ attr_accessor :action_was
+ end
+end
+
+class WeirdActionJackson < Chef::Resource
+ use_automatic_resource_name
+
+ class <<self
+ attr_accessor :action_was
+ end
+
+ action :Straße do
+ WeirdActionJackson.action_was = action
+ end
+end
+
# Houses any classes we declare
module ResourceActionSpec
@@ -229,7 +254,7 @@ module ResourceActionSpec
end
context "And 'action_jackgrandson' inheriting from ActionJackson and changing nothing" do
- before(:context) do
+ before(:each) do
class ActionJackgrandson < ActionJackson
use_automatic_resource_name
end
@@ -333,19 +358,6 @@ module ResourceActionSpec
end
context "With a resource with no actions" do
- class NoActionJackson < Chef::Resource
- use_automatic_resource_name
-
- def foo(value = nil)
- @foo = value if value
- @foo
- end
-
- class <<self
- attr_accessor :action_was
- end
- end
-
it "the default action is :nothing" do
converge do
no_action_jackson "hi" do
@@ -358,18 +370,6 @@ module ResourceActionSpec
end
context "With a resource with a UTF-8 action" do
- class WeirdActionJackson < Chef::Resource
- use_automatic_resource_name
-
- class <<self
- attr_accessor :action_was
- end
-
- action :Straße do
- WeirdActionJackson.action_was = action
- end
- end
-
it "Running the action works" do
expect_recipe do
weird_action_jackson "hi"
@@ -509,7 +509,7 @@ module ResourceActionSpec
Chef::Config[:treat_deprecation_warnings_as_errors] = false
expect_converge do
has_property_named_template "hi"
- end.to raise_error(/Property `template` of `has_property_named_template\[hi\]` was incorrectly passed a block. Possible property-resource collision. To call a resource named `template` either rename the property or else use `declare_resource\(:template, ...\)`/)
+ end.to raise_error(/Property `template` of `has_property_named_template\[hi\]` was incorrectly passed a block. Possible property-resource collision. To call a resource named `template` either rename the property or else use `declare_resource\(:template, ...\)`/)
end
end
diff --git a/spec/integration/recipes/resource_converge_if_changed_spec.rb b/spec/integration/recipes/resource_converge_if_changed_spec.rb
index 89d831ddec..f0ba4822a7 100644
--- a/spec/integration/recipes/resource_converge_if_changed_spec.rb
+++ b/spec/integration/recipes/resource_converge_if_changed_spec.rb
@@ -17,7 +17,7 @@ describe "Resource::ActionClass#converge_if_changed" do
before { Namer.current_index += 1 }
before { Namer.incrementing_value = 0 }
- context "when the resource has identity, state and control properties" do
+ context "when the resource has identity, state, control, and sensitive properties" do
let(:resource_name) { :"converge_if_changed_dsl#{Namer.current_index}" }
let(:resource_class) do
result = Class.new(Chef::Resource) do
@@ -28,6 +28,7 @@ describe "Resource::ActionClass#converge_if_changed" do
property :control1, desired_state: false, default: "default_control1"
property :state1, default: "default_state1"
property :state2, default: "default_state2"
+ property :sensitive1, default: "default_dontprintme", sensitive: true
attr_accessor :converged
def initialize(*args)
super
@@ -54,6 +55,7 @@ describe "Resource::ActionClass#converge_if_changed" do
resource_class.load_current_value do
state1 "current_state1"
state2 "current_state2"
+ sensitive1 "current_dontprintme"
end
end
@@ -134,6 +136,26 @@ EOM
end
end
+ context "and sensitive1 is set to a new value" do
+ let(:converge_recipe) do
+ <<-EOM
+ #{resource_name} 'blah' do
+ sensitive1 'new_dontprintme'
+ end
+ EOM
+ end
+
+ it "the resource updates sensitive1" do
+ expect(resource.converged).to eq 1
+ expect(resource.updated?).to be_truthy
+ expect(converged_recipe.stdout).to eq <<-EOM
+* #{resource_name}[blah] action create
+ - update default_identity1
+ - set sensitive1 to (suppressed sensitive property)
+EOM
+ end
+ end
+
context "and state1 is set to its current value but state2 is set to a new value" do
let(:converge_recipe) do
<<-EOM
@@ -244,19 +266,21 @@ EOM
expect(converged_recipe.stdout).to eq <<-EOM
* #{resource_name}[blah] action create
- create default_identity1
- - set identity1 to "default_identity1" (default value)
- - set state1 to "default_state1" (default value)
- - set state2 to "default_state2" (default value)
+ - set identity1 to "default_identity1" (default value)
+ - set state1 to "default_state1" (default value)
+ - set state2 to "default_state2" (default value)
+ - set sensitive1 to (suppressed sensitive property) (default value)
EOM
end
end
- context "and state1 and state2 are set" do
+ context "and state1, state2, and sensitive1 are set" do
let(:converge_recipe) do
<<-EOM
#{resource_name} 'blah' do
state1 'new_state1'
state2 'new_state2'
+ sensitive1 'new_dontprintme'
end
EOM
end
@@ -267,9 +291,10 @@ EOM
expect(converged_recipe.stdout).to eq <<-EOM
* #{resource_name}[blah] action create
- create default_identity1
- - set identity1 to "default_identity1" (default value)
- - set state1 to "new_state1"
- - set state2 to "new_state2"
+ - set identity1 to "default_identity1" (default value)
+ - set state1 to "new_state1"
+ - set state2 to "new_state2"
+ - set sensitive1 to (suppressed sensitive property)
EOM
end
end
@@ -291,9 +316,10 @@ EOM
expect(converged_recipe.stdout).to eq <<-EOM
* #{resource_name}[blah] action create
- create default_identity1
- - set identity1 to (suppressed sensitive property) (default value)
- - set state1 to (suppressed sensitive property)
- - set state2 to (suppressed sensitive property)
+ - set identity1 to (suppressed sensitive property) (default value)
+ - set state1 to (suppressed sensitive property)
+ - set state2 to (suppressed sensitive property)
+ - set sensitive1 to (suppressed sensitive property) (default value)
EOM
end
end
@@ -309,6 +335,9 @@ EOM
converge_if_changed :state2 do
new_resource.converged += 1
end
+ converge_if_changed :sensitive1 do
+ new_resource.converged += 1
+ end
end
end
@@ -415,6 +444,26 @@ EOM
EOM
end
end
+
+ context "and sensitive1 is set to a new value" do
+ let(:converge_recipe) do
+ <<-EOM
+ #{resource_name} 'blah' do
+ sensitive1 'new_dontprintme'
+ end
+ EOM
+ end
+
+ it "the resource updates sensitive1" do
+ expect(resource.converged).to eq 1
+ expect(resource.updated?).to be_truthy
+ expect(converged_recipe.stdout).to eq <<-EOM
+* #{resource_name}[blah] action create
+ - update default_identity1
+ - set sensitive1 to (suppressed sensitive property)
+EOM
+ end
+ end
end
context "and no current_resource" do
@@ -430,7 +479,7 @@ EOM
end
it "the resource is created" do
- expect(resource.converged).to eq 2
+ expect(resource.converged).to eq 3
expect(resource.updated?).to be_truthy
expect(converged_recipe.stdout).to eq <<-EOM
* #{resource_name}[blah] action create
@@ -438,22 +487,25 @@ EOM
- set state1 to "default_state1" (default value)
- create default_identity1
- set state2 to "default_state2" (default value)
+ - create default_identity1
+ - set sensitive1 to (suppressed sensitive property) (default value)
EOM
end
end
- context "and state1 and state2 are set to new values" do
+ context "and state1, state2, and sensitive1 are set to new values" do
let(:converge_recipe) do
<<-EOM
#{resource_name} 'blah' do
state1 'new_state1'
state2 'new_state2'
+ sensitive1 'new_dontprintme'
end
EOM
end
it "the resource is created" do
- expect(resource.converged).to eq 2
+ expect(resource.converged).to eq 3
expect(resource.updated?).to be_truthy
expect(converged_recipe.stdout).to eq <<-EOM
* #{resource_name}[blah] action create
@@ -461,6 +513,8 @@ EOM
- set state1 to "new_state1"
- create default_identity1
- set state2 to "new_state2"
+ - create default_identity1
+ - set sensitive1 to (suppressed sensitive property)
EOM
end
end
@@ -477,7 +531,7 @@ EOM
end
it "the resource is created" do
- expect(resource.converged).to eq 2
+ expect(resource.converged).to eq 3
expect(resource.updated?).to be_truthy
expect(converged_recipe.stdout).to eq <<-EOM
* #{resource_name}[blah] action create
@@ -485,6 +539,8 @@ EOM
- set state1 to (suppressed sensitive property)
- create default_identity1
- set state2 to (suppressed sensitive property)
+ - create default_identity1
+ - set sensitive1 to (suppressed sensitive property) (default value)
EOM
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index bace94fcbe..10e9818834 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -111,6 +111,11 @@ TEST_PLATFORM = TEST_NODE["platform"]
TEST_PLATFORM_VERSION = TEST_NODE["platform_version"]
TEST_PLATFORM_FAMILY = TEST_NODE["platform_family"]
+provider_priority_map ||= nil
+resource_priority_map ||= nil
+provider_handler_map ||= nil
+resource_handler_map ||= nil
+
RSpec.configure do |config|
config.include(Matchers)
config.include(MockShellout::RSpec)
@@ -233,6 +238,20 @@ RSpec.configure do |config|
# Set environment variable so the setting persists in child processes
ENV["CHEF_TREAT_DEPRECATION_WARNINGS_AS_ERRORS"] = "1"
+
+ # we don't perfectly reset the priority/handler maps here, but by dup'ing the top level hash we
+ # throw away all the garbage resources and providers that we setup. if we mutate something like
+ # :package then that'll carry over from test-to-test, but the solution would be to deep-dup on every
+ # single test we run which is much more expensive. by throwing away the garbage top level keys we
+ # significantly speed up test runs.
+ provider_handler_map ||= Chef.provider_handler_map.send(:map).dup
+ resource_handler_map ||= Chef.resource_handler_map.send(:map).dup
+ provider_priority_map ||= Chef.provider_priority_map.send(:map).dup
+ resource_priority_map ||= Chef.resource_priority_map.send(:map).dup
+ Chef.provider_handler_map.instance_variable_set(:@map, provider_handler_map.dup)
+ Chef.resource_handler_map.instance_variable_set(:@map, resource_handler_map.dup)
+ Chef.provider_priority_map.instance_variable_set(:@map, provider_priority_map.dup)
+ Chef.resource_priority_map.instance_variable_set(:@map, resource_priority_map.dup)
end
# raise if anyone commits any test to CI with :focus set on it
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 ef03a1133e..4dcbf1e60b 100644
--- a/spec/support/lib/chef/resource/one_two_three_four.rb
+++ b/spec/support/lib/chef/resource/one_two_three_four.rb
@@ -21,8 +21,6 @@ class Chef
class OneTwoThreeFour < Chef::Resource
provides :one_two_three_four
- attr_reader :i_can_count
-
def i_can_count(tf)
@i_can_count = tf
end
diff --git a/spec/support/lib/chef/resource/zen_master.rb b/spec/support/lib/chef/resource/zen_master.rb
index 99d761c8cf..9d6e5d46f7 100644
--- a/spec/support/lib/chef/resource/zen_master.rb
+++ b/spec/support/lib/chef/resource/zen_master.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,8 +25,6 @@ class Chef
provides :zen_master
allowed_actions :win, :score
- attr_reader :peace
-
def peace(tf)
@peace = tf
end
diff --git a/spec/support/mock/constant.rb b/spec/support/mock/constant.rb
index 3a23b4d8d8..7acd02e9d7 100644
--- a/spec/support/mock/constant.rb
+++ b/spec/support/mock/constant.rb
@@ -15,7 +15,7 @@ def mock_constants(constants)
begin
yield
ensure
- constants.each do |constant, val|
+ constants.each_key do |constant|
source_object, const_name = parse_constant(constant)
with_warnings(nil) { source_object.const_set(const_name, saved_constants[constant]) }
end
diff --git a/spec/support/shared/functional/execute_resource.rb b/spec/support/shared/functional/execute_resource.rb
index 4f7cea1cd1..1a14bb38c3 100644
--- a/spec/support/shared/functional/execute_resource.rb
+++ b/spec/support/shared/functional/execute_resource.rb
@@ -63,7 +63,7 @@ shared_context "a command that can be executed as an alternate user" do
after do
File.delete(script_output_path) if File.exists?(script_output_path)
- Dir.rmdir(script_output_dir) if Dir.exists?(script_output_dir)
+ Dir.rmdir(script_output_dir) if Dir.exist?(script_output_dir)
end
end
diff --git a/spec/support/shared/integration/knife_support.rb b/spec/support/shared/integration/knife_support.rb
index d873723784..86764cad66 100644
--- a/spec/support/shared/integration/knife_support.rb
+++ b/spec/support/shared/integration/knife_support.rb
@@ -83,6 +83,11 @@ module KnifeSupport
# running test scenarios against a real chef server. If things don't
# smell right, abort.
+ # To ensure that we don't pick up a user's credentials file we lie through our teeth about
+ # it's existence.
+ allow(File).to receive(:file?).and_call_original
+ allow(File).to receive(:file?).with(File.expand_path("~/.chef/credentials")).and_return(false)
+
$__KNIFE_INTEGRATION_FAILSAFE_CHECK = "ole"
instance.configure_chef
diff --git a/spec/support/shared/unit/application_dot_d.rb b/spec/support/shared/unit/application_dot_d.rb
index da4eb88edd..b94fa7c184 100644
--- a/spec/support/shared/unit/application_dot_d.rb
+++ b/spec/support/shared/unit/application_dot_d.rb
@@ -38,9 +38,11 @@ shared_examples_for "an application that loads a dot d" do
it "loads the configuration in order" do
expect(IO).to receive(:read).with(Pathname.new("#{client_d_dir}/00-foo.rb").cleanpath.to_s).and_return("foo 0")
expect(IO).to receive(:read).with(Pathname.new("#{client_d_dir}/01-bar.rb").cleanpath.to_s).and_return("bar 0")
+ expect(IO).to receive(:read).with(Pathname.new("#{client_d_dir}/02-strings.rb").cleanpath.to_s).and_return("strings 0")
allow(app).to receive(:apply_config).with(anything(), Chef::Config.platform_specific_path("/etc/chef/client.rb")).and_call_original.ordered
expect(app).to receive(:apply_config).with("foo 0", Pathname.new("#{client_d_dir}/00-foo.rb").cleanpath.to_s).and_call_original.ordered
expect(app).to receive(:apply_config).with("bar 0", Pathname.new("#{client_d_dir}/01-bar.rb").cleanpath.to_s).and_call_original.ordered
+ expect(app).to receive(:apply_config).with("strings 0", Pathname.new("#{client_d_dir}/02-strings.rb").cleanpath.to_s).and_call_original.ordered
app.reconfigure
end
end
diff --git a/spec/support/shared/unit/execute_resource.rb b/spec/support/shared/unit/execute_resource.rb
index ae56a9697d..c15b02612e 100644
--- a/spec/support/shared/unit/execute_resource.rb
+++ b/spec/support/shared/unit/execute_resource.rb
@@ -139,7 +139,14 @@ shared_examples_for "an execute resource" do
it "should be true if the password is non-nil but the value is explicitly set to false" do
@resource.password("we.funk!")
@resource.sensitive false
- expect(@resource.sensitive).to eq(true)
+ expect(@resource.sensitive).to eq(false)
+ end
+
+ # added this test to ensure setting of password property after or before sensitive does not matter
+ it "should be false if the sensitive is set before password property" do
+ @resource.sensitive false
+ @resource.password("we.funk!")
+ expect(@resource.sensitive).to eq(false)
end
end
diff --git a/spec/support/shared/unit/provider/file.rb b/spec/support/shared/unit/provider/file.rb
index b58159fcc9..d508e76b24 100644
--- a/spec/support/shared/unit/provider/file.rb
+++ b/spec/support/shared/unit/provider/file.rb
@@ -476,7 +476,15 @@ shared_examples_for Chef::Provider::File do
allow(File).to receive(:directory?).with("C:\\Windows\\system32/cmd.exe").and_return(false)
provider.new_resource.verify windows? ? "REM" : "true"
provider.new_resource.verify windows? ? "cmd.exe /c exit 1" : "false"
- expect { provider.send(:do_validate_content) }.to raise_error(Chef::Exceptions::ValidationFailed)
+ expect { provider.send(:do_validate_content) }.to raise_error(Chef::Exceptions::ValidationFailed, "Proposed content for #{provider.new_resource.path} failed verification #{windows? ? "cmd.exe /c exit 1" : "false"}")
+ end
+
+ it "does not show verification for sensitive resources" do
+ allow(File).to receive(:directory?).with("C:\\Windows\\system32/cmd.exe").and_return(false)
+ provider.new_resource.verify windows? ? "REM" : "true"
+ provider.new_resource.verify windows? ? "cmd.exe /c exit 1" : "false"
+ provider.new_resource.sensitive true
+ expect { provider.send(:do_validate_content) }.to raise_error(Chef::Exceptions::ValidationFailed, "Proposed content for #{provider.new_resource.path} failed verification [sensitive]")
end
end
end
diff --git a/spec/unit/application/solo_spec.rb b/spec/unit/application/solo_spec.rb
index 686ae745d8..5b9dbeaafd 100644
--- a/spec/unit/application/solo_spec.rb
+++ b/spec/unit/application/solo_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: AJ Christensen (<aj@junglist.gen.nz>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -203,13 +203,6 @@ Enable chef-client interval runs by setting `:client_fork = true` in your config
app.reconfigure
expect(ARGV.include?("--ez")).to be_falsey
end
-
- it "replaces -r with --recipe-url" do
- ARGV.push("-r", "http://junglist.gen.nz/recipes.tgz")
- app.reconfigure
- expect(ARGV.include?("-r")).to be_falsey
- expect(ARGV.include?("--recipe-url")).to be_truthy
- end
end
it "sets the repo path" do
diff --git a/spec/unit/audit/audit_reporter_spec.rb b/spec/unit/audit/audit_reporter_spec.rb
index cf916266d8..5239364113 100644
--- a/spec/unit/audit/audit_reporter_spec.rb
+++ b/spec/unit/audit/audit_reporter_spec.rb
@@ -2,7 +2,7 @@
# Author:: Tyler Ball (<tball@chef.io>)
# Author:: Claire McQuin (<claire@chef.io>)
#
-# Copyright:: Copyright 2014-2016, Chef Software, Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -319,7 +319,7 @@ EOM
end
it "collects audit data" do
- ordered_control_groups.each do |_name, group|
+ ordered_control_groups.each_value do |group|
expect(audit_data).to receive(:add_control_group).with(group)
end
reporter.audit_phase_complete("Output from audit mode")
@@ -337,7 +337,7 @@ EOM
end
it "collects audit data" do
- ordered_control_groups.each do |_name, group|
+ ordered_control_groups.each_value do |group|
expect(audit_data).to receive(:add_control_group).with(group)
end
reporter.audit_phase_failed(error, "Output from audit mode")
diff --git a/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb b/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb
new file mode 100644
index 0000000000..6d6e2fb0e6
--- /dev/null
+++ b/spec/unit/chef_fs/data_handler/data_bag_item_data_handler.rb
@@ -0,0 +1,82 @@
+#
+# Author:: Sandra Tiffin (<sandi.tiffin@gmail.com>)
+# Copyright:: Copyright 2014-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 "lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb"
+
+class TestDataBag < Mash
+ attr_accessor :name
+
+ def initialize(bag_name)
+ @name = bag_name
+ end
+end
+
+class TestDataBagItem < Mash
+ attr_accessor :name, :parent
+
+ def path_for_printing
+ "/some/path"
+ end
+
+ def initialize(bag_name, item_name)
+ @name = "#{item_name}.json"
+ @parent = TestDataBag.new(bag_name)
+ end
+end
+
+describe Chef::ChefFS::DataHandler::DataBagItemDataHandler do
+ let(:handler) { described_class.new }
+
+ describe "#verify_integrity" do
+ context "json id does not match data bag item name" do
+ let(:entry) { TestDataBagItem.new("luggage", "bag") }
+ let(:object) do
+ { "raw_data" => { "id" => "duffel" } }
+ end
+ it "rejects the data bag item name" do
+ expect { |b| handler.verify_integrity(object, entry, &b) }.to yield_with_args
+ end
+ end
+
+ context "using a reserved word for the data bag name" do
+ %w{node role environment client}.each do |reserved_word|
+ let(:entry) { TestDataBagItem.new(reserved_word, "bag") }
+ let(:object) do
+ { "raw_data" => { "id" => "bag" } }
+ end
+ it "rejects the data bag name '#{reserved_word}'" do
+ expect { |b| handler.verify_integrity(object, entry, &b) }.to yield_with_args
+ end
+ end
+ end
+
+ context "using a reserved word as part of the data bag name" do
+ %w{xnode rolex xenvironmentx xclientx}.each do |bag_name|
+ let(:entry) { TestDataBagItem.new("#{bag_name}", "bag") }
+ let(:object) do
+ { "raw_data" => { "id" => "bag" } }
+ end
+ it "allows the data bag name '#{bag_name}'" do
+ expect(handler.verify_integrity(object, entry)).to be_nil
+ end
+ end
+ end
+
+ end
+end
diff --git a/spec/unit/chef_fs/file_system/repository/directory_spec.rb b/spec/unit/chef_fs/file_system/repository/directory_spec.rb
index 6e53e52966..e44cc15167 100644
--- a/spec/unit/chef_fs/file_system/repository/directory_spec.rb
+++ b/spec/unit/chef_fs/file_system/repository/directory_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Thom May (<thom@chef.io>)
-# Copyright:: Copyright 2012-2016, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -152,7 +152,7 @@ describe Chef::ChefFS::FileSystem::Repository::Directory do
end
after do
- FileUtils.rmdir(tmp_dir)
+ FileUtils.rm_rf(tmp_dir)
end
end
diff --git a/spec/unit/chef_fs/file_system_spec.rb b/spec/unit/chef_fs/file_system_spec.rb
index 5c74729557..c7ed83524b 100644
--- a/spec/unit/chef_fs/file_system_spec.rb
+++ b/spec/unit/chef_fs/file_system_spec.rb
@@ -140,7 +140,7 @@ describe Chef::ChefFS::FileSystem do
it "is empty /y" do
expect(Chef::ChefFS::FileSystem.resolve_path(fs, "/y").empty?).to be true
end
- it 'is not a directory and can\'t be tested /x' do
+ it "is not a directory and can't be tested /x" do
expect { Chef::ChefFS::FileSystem.resolve_path(fs, "/x").empty? }.to raise_error(NoMethodError)
end
end
diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb
index d348c24385..2aff7b2a71 100644
--- a/spec/unit/client_spec.rb
+++ b/spec/unit/client_spec.rb
@@ -38,12 +38,23 @@ describe Chef::Client do
end
it "runs ohai with only the minimum required plugins" do
- expected_filter = %w{fqdn machinename hostname platform platform_version os os_version}
+ expected_filter = %w{fqdn machinename hostname platform platform_version ohai_time os os_version}
expect(ohai_system).to receive(:all_plugins).with(expected_filter)
client.run_ohai
end
end
+ context "when Ohai tells us to fail" do
+ it "fails" do
+ ohai_system = Ohai::System.new
+ module Ohai::Exceptions
+ class CriticalPluginFailure < Error; end
+ end
+ expect(ohai_system).to receive(:all_plugins) { raise Ohai::Exceptions::CriticalPluginFailure }
+ expect { client.run_ohai }.to raise_error(SystemExit)
+ end
+ end
+
describe "authentication protocol selection" do
context "when FIPS is disabled" do
before do
diff --git a/spec/unit/cookbook/synchronizer_spec.rb b/spec/unit/cookbook/synchronizer_spec.rb
index 6578a9e670..1e6c9ef48c 100644
--- a/spec/unit/cookbook/synchronizer_spec.rb
+++ b/spec/unit/cookbook/synchronizer_spec.rb
@@ -116,9 +116,12 @@ describe Chef::CookbookSynchronizer do
let(:no_lazy_load) { true }
+ let(:skip_cookbook_sync) { false }
+
let(:synchronizer) do
Chef::Config[:no_lazy_load] = no_lazy_load
Chef::Config[:file_cache_path] = "/file-cache"
+ Chef::Config[:skip_cookbook_sync] = skip_cookbook_sync
Chef::CookbookSynchronizer.new(cookbook_manifest, events)
end
@@ -523,5 +526,32 @@ describe Chef::CookbookSynchronizer do
end
end
end
+
+ context "when Chef::Config[:skip_cookbook_sync] is true" do
+ let(:skip_cookbook_sync) { true }
+
+ it "loads the cookbook files and warns the user that this isn't supported" do
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/recipes/default.rb", false).
+ once.
+ and_return("/file-cache/cookbooks/cookbook_a/recipes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/attributes/default.rb", false).
+ once.
+ and_return("/file-cache/cookbooks/cookbook_a/attributes/default.rb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/templates/default/apache2.conf.erb", false).
+ once.
+ and_return("/file-cache/cookbooks/cookbook_a/templates/default/apache2.conf.erb")
+ expect(file_cache).to receive(:load).
+ with("cookbooks/cookbook_a/files/default/megaman.conf", false).
+ once.
+ and_return("/file-cache/cookbooks/cookbook_a/files/default/megaman.conf")
+ expect(Chef::Log).to receive(:warn).
+ with("skipping cookbook synchronization! DO NOT LEAVE THIS ENABLED IN PRODUCTION!!!").
+ once
+ synchronizer.sync_cookbooks
+ end
+ end
end
end
diff --git a/spec/unit/cookbook_loader_spec.rb b/spec/unit/cookbook_loader_spec.rb
index a5fb622da0..19f3160d0c 100644
--- a/spec/unit/cookbook_loader_spec.rb
+++ b/spec/unit/cookbook_loader_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -87,7 +87,7 @@ describe Chef::CookbookLoader do
describe "each" do
it "should allow you to iterate over cookbooks with each" do
seen = Hash.new
- cookbook_loader.each do |cookbook_name, cookbook|
+ cookbook_loader.each_key do |cookbook_name|
seen[cookbook_name] = true
end
expect(seen).to have_key("openldap")
@@ -96,7 +96,7 @@ describe Chef::CookbookLoader do
it "should iterate in alphabetical order" do
seen = Array.new
- cookbook_loader.each do |cookbook_name, cookbook|
+ cookbook_loader.each_key do |cookbook_name|
seen << cookbook_name
end
expect(seen).to eq %w{angrybash apache2 borken ignorken java name-mismatch openldap preseed supports-platform-constraints}
@@ -206,7 +206,7 @@ describe Chef::CookbookLoader do
it "should have loaded the correct cookbook" do
seen = Hash.new
- cookbook_loader.each do |cookbook_name, cookbook|
+ cookbook_loader.each_key do |cookbook_name|
seen[cookbook_name] = true
end
expect(seen).to have_key("openldap")
@@ -234,7 +234,7 @@ describe Chef::CookbookLoader do
it "should not load the other cookbooks" do
seen = Hash.new
- cookbook_loader.each do |cookbook_name, cookbook|
+ cookbook_loader.each_key do |cookbook_name|
seen[cookbook_name] = true
end
expect(seen).not_to have_key("apache2")
@@ -272,7 +272,7 @@ describe Chef::CookbookLoader do
it "should load all cookbooks" do
seen = Hash.new
- cookbook_loader.each do |cookbook_name, cookbook|
+ cookbook_loader.each_key do |cookbook_name|
seen[cookbook_name] = true
end
expect(seen).to have_key("openldap")
diff --git a/spec/unit/cookbook_manifest_spec.rb b/spec/unit/cookbook_manifest_spec.rb
index a28eaff3d3..ab4b5cbfb7 100644
--- a/spec/unit/cookbook_manifest_spec.rb
+++ b/spec/unit/cookbook_manifest_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2015-2016, Chef Software Inc.
+# Copyright:: Copyright 2015-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -162,7 +162,7 @@ describe Chef::CookbookManifest do
cookbook_manifest_hash = cookbook_manifest.to_hash
expect(cookbook_manifest_hash.keys).to match_array(expected_hash.keys)
- cookbook_manifest_hash.each do |key, value|
+ cookbook_manifest_hash.each_key do |key|
expect(cookbook_manifest_hash[key]).to eq(expected_hash[key])
end
end
diff --git a/spec/unit/data_collector/resource_report_spec.rb b/spec/unit/data_collector/resource_report_spec.rb
index b3523622c4..278e94b53b 100644
--- a/spec/unit/data_collector/resource_report_spec.rb
+++ b/spec/unit/data_collector/resource_report_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Salim Afiune (<afiune@chef.io)
#
-# Copyright:: Copyright 2012-2017, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -110,7 +110,7 @@ describe Chef::DataCollector::ResourceReport do
context "for a lazy_resource that got skipped" do
let(:resource) do
klass = Class.new(Chef::Resource) do
- resource_name "link"
+ resource_name "butters"
property :sword, String, name_property: true, identity: true
end
resource = klass.new("hyrule")
@@ -129,7 +129,7 @@ describe Chef::DataCollector::ResourceReport do
"name" => "hyrule",
"result" => "create",
"status" => "skipped",
- "type" => :link,
+ "type" => :butters,
}
end
let(:conditional) do
diff --git a/spec/unit/deprecated_spec.rb b/spec/unit/deprecated_spec.rb
index 9be792ab20..4eba764b63 100644
--- a/spec/unit/deprecated_spec.rb
+++ b/spec/unit/deprecated_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2013-2016, Chef Software Inc.
+# Copyright:: Copyright 2013-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -29,7 +29,7 @@ describe Chef::Deprecated do
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)
+ expect(Chef::Deprecated.create(:test_deprecation)).to be_an_instance_of(TestDeprecation)
end
it "optionally sets a message" do
@@ -49,11 +49,11 @@ describe Chef::Deprecated do
let(:location) { "the location" }
it "displays the full URL" do
- expect(Chef::Deprecated::TestDeprecation.new().url).to eql("#{base_url}test.html")
+ expect(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")
+ expect(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/dsl/recipe_spec.rb b/spec/unit/dsl/recipe_spec.rb
index bc97ecc029..cd01079c15 100644
--- a/spec/unit/dsl/recipe_spec.rb
+++ b/spec/unit/dsl/recipe_spec.rb
@@ -24,11 +24,6 @@ class RecipeDSLExampleClass
include Chef::DSL::Recipe
end
-FullRecipeDSLExampleClass = Struct.new(:cookbook_name, :recipe_name)
-class FullRecipeDSLExampleClass
- include Chef::DSL::Recipe::FullDSL
-end
-
RecipeDSLBaseAPI = Struct.new(:cookbook_name, :recipe_name)
class RecipeDSLExampleSubclass < RecipeDSLBaseAPI
include Chef::DSL::Recipe
@@ -41,14 +36,6 @@ describe Chef::DSL::Recipe do
let(:cookbook_name) { "example_cb" }
let(:recipe_name) { "example_recipe" }
- it "tracks when it is included via FullDSL" do
- expect(Chef::DSL::Recipe::FullDSL.descendants).to include(FullRecipeDSLExampleClass)
- end
-
- it "doesn't track what is included via only the recipe DSL" do
- expect(Chef::DSL::Recipe::FullDSL.descendants).not_to include(RecipeDSLExampleClass)
- end
-
shared_examples_for "A Recipe DSL Implementation" do
it "responds to cookbook_name" do
diff --git a/spec/unit/environment_spec.rb b/spec/unit/environment_spec.rb
index 3daae16749..c604148ec8 100644
--- a/spec/unit/environment_spec.rb
+++ b/spec/unit/environment_spec.rb
@@ -3,7 +3,7 @@
# Author:: Seth Falcon (<seth@ospcode.com>)
# Author:: John Keiser (<jkeiser@ospcode.com>)
# Author:: Kyle Goodwin (<kgoodwin@primerevenue.com>)
-# Copyright:: Copyright 2010-2016, Chef Software Inc.
+# Copyright:: Copyright 2010-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -250,7 +250,7 @@ describe Chef::Environment do
end
it "should validate the version string of each cookbook" do
- @cookbook_versions.each do |cookbook, version|
+ @cookbook_versions.each_value do |version|
expect(Chef::Environment).to receive(:validate_cookbook_version).with(version).and_return true
end
Chef::Environment.validate_cookbook_versions(@cookbook_versions)
diff --git a/spec/unit/http_spec.rb b/spec/unit/http_spec.rb
index d58f07c417..bf873b8535 100644
--- a/spec/unit/http_spec.rb
+++ b/spec/unit/http_spec.rb
@@ -93,6 +93,15 @@ describe Chef::HTTP do
expect { http.send(:stream_to_tempfile, uri, resp) }.to raise_error("TestError")
end
+ it "accepts a tempfile" do
+ resp = Net::HTTPOK.new("1.1", 200, "OK")
+ http = Chef::HTTP.new(uri)
+ tempfile = Tempfile.open("tempy-mctempfile")
+ expect(Tempfile).not_to receive(:open)
+ expect(resp).to receive(:read_body).and_yield("conty-mccontent")
+ http.send(:stream_to_tempfile, uri, resp, tempfile)
+ expect(IO.read(tempfile.path)).to eql("conty-mccontent")
+ end
end
describe "head" do
diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb
index 736ff9b099..c725526de7 100644
--- a/spec/unit/knife/bootstrap_spec.rb
+++ b/spec/unit/knife/bootstrap_spec.rb
@@ -516,6 +516,11 @@ describe Chef::Knife::Bootstrap do
end
context "a flat directory structure" do
+ it "escapes single-quotes" do
+ expect(rendered_template).to match("cat > /etc/chef/client.d/02-strings.rb <<'EOP'")
+ expect(rendered_template).to match("something '\\\\''/foo/bar'\\\\''")
+ end
+
it "creates a file 00-foo.rb" do
expect(rendered_template).to match("cat > /etc/chef/client.d/00-foo.rb <<'EOP'")
expect(rendered_template).to match("d6f9b976-289c-4149-baf7-81e6ffecf228")
diff --git a/spec/unit/knife/configure_spec.rb b/spec/unit/knife/configure_spec.rb
index b7802d3890..f1d3bd0745 100644
--- a/spec/unit/knife/configure_spec.rb
+++ b/spec/unit/knife/configure_spec.rb
@@ -124,55 +124,12 @@ describe Chef::Knife::Configure do
end
end
- it "asks the user for the location of a chef repo" do
- @knife.ask_user_for_config
- expect(@out.string).to match(Regexp.escape("Please enter the path to a chef repository (or leave blank):"))
- expect(@knife.chef_repo).to eq("")
- end
-
- it "asks the users for the name of the validation client" do
- @knife.ask_user_for_config
- expect(@out.string).to match(Regexp.escape("Please enter the validation clientname: [chef-validator]"))
- expect(@knife.validation_client_name).to eq("chef-validator")
- end
-
- it "should not ask the users for the name of the validation client if --validation_client_name is specified" do
- @knife.config[:validation_client_name] = "my-validator"
- @knife.ask_user_for_config
- expect(@out.string).not_to match(Regexp.escape("Please enter the validation clientname:"))
- expect(@knife.validation_client_name).to eq("my-validator")
- end
-
- it "asks the users for the location of the validation key" do
- @knife.ask_user_for_config
- expect(@out.string).to match(Regexp.escape("Please enter the location of the validation key: [#{default_validator_key}]"))
- if windows?
- expect(@knife.validation_key.capitalize).to eq(default_validator_key_win32.capitalize)
- else
- expect(@knife.validation_key).to eq(default_validator_key)
- end
- end
-
- it "should not ask the users for the location of the validation key if --validation_key is specified" do
- @knife.config[:validation_key] = "/home/you/.chef/my-validation.pem"
- @knife.ask_user_for_config
- expect(@out.string).not_to match(Regexp.escape("Please enter the location of the validation key:"))
- if windows?
- expect(@knife.validation_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-validation\.pem$}
- else
- expect(@knife.validation_key).to eq("/home/you/.chef/my-validation.pem")
- end
- end
-
it "should not ask the user for anything if -i and all other properties are specified" do
@knife.config[:initial] = true
@knife.config[:chef_server_url] = "http://localhost:5000"
@knife.config[:node_name] = "testnode"
@knife.config[:admin_client_name] = "my-webui"
@knife.config[:admin_client_key] = "/home/you/.chef/my-webui.pem"
- @knife.config[:validation_client_name] = "my-validator"
- @knife.config[:validation_key] = "/home/you/.chef/my-validation.pem"
- @knife.config[:repository] = ""
@knife.config[:client_key] = "/home/you/a-new-user.pem"
allow(Etc).to receive(:getlogin).and_return("a-new-user")
@@ -184,40 +141,33 @@ describe Chef::Knife::Configure do
expect(@knife.admin_client_name).to eq("my-webui")
if windows?
expect(@knife.admin_client_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-webui\.pem$}
- expect(@knife.validation_key).to match %r{^[A-Za-z]:/home/you/\.chef/my-validation\.pem$}
expect(@knife.new_client_key).to match %r{^[A-Za-z]:/home/you/a-new-user\.pem$}
else
expect(@knife.admin_client_key).to eq("/home/you/.chef/my-webui.pem")
- expect(@knife.validation_key).to eq("/home/you/.chef/my-validation.pem")
expect(@knife.new_client_key).to eq("/home/you/a-new-user.pem")
end
- expect(@knife.validation_client_name).to eq("my-validator")
- expect(@knife.chef_repo).to eq("")
end
it "writes the new data to a config file" do
- allow(File).to receive(:expand_path).with("/home/you/.chef/knife.rb").and_return("/home/you/.chef/knife.rb")
+ allow(Chef::Util::PathHelper).to receive(:home).with(".chef").and_return("/home/you/.chef")
+ allow(File).to receive(:expand_path).with("/home/you/.chef/credentials").and_return("/home/you/.chef/credentials")
allow(File).to receive(:expand_path).with("/home/you/.chef/#{Etc.getlogin}.pem").and_return("/home/you/.chef/#{Etc.getlogin}.pem")
- allow(File).to receive(:expand_path).with(default_validator_key).and_return(default_validator_key)
allow(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key)
expect(FileUtils).to receive(:mkdir_p).with("/home/you/.chef")
config_file = StringIO.new
- expect(::File).to receive(:open).with("/home/you/.chef/knife.rb", "w").and_yield config_file
+ expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w").and_yield config_file
@knife.config[:repository] = "/home/you/chef-repo"
@knife.run
- expect(config_file.string).to match(/^node_name[\s]+'#{Etc.getlogin}'$/)
- expect(config_file.string).to match(%r{^client_key[\s]+'/home/you/.chef/#{Etc.getlogin}.pem'$})
- expect(config_file.string).to match(/^validation_client_name\s+'chef-validator'$/)
- expect(config_file.string).to match(%r{^validation_key\s+'#{default_validator_key}'$})
- expect(config_file.string).to match(%r{^chef_server_url\s+'#{default_server_url}'$})
- expect(config_file.string).to match(%r{cookbook_path\s+\[ '/home/you/chef-repo/cookbooks' \]})
+ expect(config_file.string).to match(/^client_name[\s]+=[\s]+'#{Etc.getlogin}'$/)
+ expect(config_file.string).to match(%r{^client_key[\s]+=[\s]+'/home/you/.chef/#{Etc.getlogin}.pem'$})
+ expect(config_file.string).to match(%r{^chef_server_url\s+=[\s]+'#{default_server_url}'$})
end
it "creates a new client when given the --initial option" do
- expect(File).to receive(:expand_path).with("/home/you/.chef/knife.rb").and_return("/home/you/.chef/knife.rb")
+ allow(Chef::Util::PathHelper).to receive(:home).with(".chef").and_return("/home/you/.chef")
+ expect(File).to receive(:expand_path).with("/home/you/.chef/credentials").and_return("/home/you/.chef/credentials")
expect(File).to receive(:expand_path).with("/home/you/.chef/a-new-user.pem").and_return("/home/you/.chef/a-new-user.pem")
- expect(File).to receive(:expand_path).with(default_validator_key).and_return(default_validator_key)
- expect(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key)
+ allow(File).to receive(:expand_path).with(default_admin_key).and_return(default_admin_key)
Chef::Config[:node_name] = "webmonkey.example.com"
user_command = Chef::Knife::UserCreate.new
@@ -227,7 +177,7 @@ describe Chef::Knife::Configure do
allow(Chef::Knife::UserCreate).to receive(:new).and_return(user_command)
expect(FileUtils).to receive(:mkdir_p).with("/home/you/.chef")
- expect(::File).to receive(:open).with("/home/you/.chef/knife.rb", "w")
+ expect(::File).to receive(:open).with("/home/you/.chef/credentials", "w")
@knife.config[:initial] = true
@knife.config[:user_password] = "blah"
@knife.run
diff --git a/spec/unit/knife/cookbook_test_spec.rb b/spec/unit/knife/cookbook_test_spec.rb
index f8b212e271..dd5d4f096a 100644
--- a/spec/unit/knife/cookbook_test_spec.rb
+++ b/spec/unit/knife/cookbook_test_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Stephen Delano (<stephen@chef.io>)$
# Author:: Matthew Kent (<mkent@magoazul.com>)
-# Copyright:: Copyright 2010-2016, Chef Software Inc.$
+# Copyright:: Copyright 2010-2018, Chef Software Inc.$
# Copyright:: Copyright 2010-2016, Matthew Kent
# License:: Apache License, Version 2.0
#
@@ -73,7 +73,7 @@ describe Chef::Knife::CookbookTest do
@loader[cookbook.name] = cookbook
end
allow(@knife).to receive(:cookbook_loader).and_return(@loader)
- @loader.each do |key, cookbook|
+ @loader.each_value do |cookbook|
expect(@knife).to receive(:test_cookbook).with(cookbook.name)
end
@knife.run
diff --git a/spec/unit/knife/core/gem_glob_loader_spec.rb b/spec/unit/knife/core/gem_glob_loader_spec.rb
index 2f9e04769e..689426de1b 100644
--- a/spec/unit/knife/core/gem_glob_loader_spec.rb
+++ b/spec/unit/knife/core/gem_glob_loader_spec.rb
@@ -40,7 +40,7 @@ describe Chef::Knife::SubcommandLoader::GemGlobLoader do
it "finds files installed via rubygems" do
expect(loader.find_subcommands_via_rubygems).to include("chef/knife/node_create")
- loader.find_subcommands_via_rubygems.each { |rel_path, abs_path| expect(abs_path).to match(%r{chef/knife/.+}) }
+ loader.find_subcommands_via_rubygems.each_value { |abs_path| expect(abs_path).to match(%r{chef/knife/.+}) }
end
it "finds files from latest version of installed gems" do
@@ -65,7 +65,7 @@ describe Chef::Knife::SubcommandLoader::GemGlobLoader do
it "finds files using a dirglob when rubygems is not available" do
expect(loader.find_subcommands_via_dirglob).to include("chef/knife/node_create")
- loader.find_subcommands_via_dirglob.each { |rel_path, abs_path| expect(abs_path).to match(%r{chef/knife/.+}) }
+ loader.find_subcommands_via_dirglob.each_value { |abs_path| expect(abs_path).to match(%r{chef/knife/.+}) }
end
it "finds user-specific subcommands in the user's ~/.chef directory" do
diff --git a/spec/unit/knife/core/node_editor_spec.rb b/spec/unit/knife/core/node_editor_spec.rb
index ce169a77dd..7e05f99f52 100644
--- a/spec/unit/knife/core/node_editor_spec.rb
+++ b/spec/unit/knife/core/node_editor_spec.rb
@@ -55,7 +55,7 @@ describe Chef::Knife::NodeEditor do
context "when config[:all_attributes] == true" do
let(:config) { base_config.merge(all_attributes: true) }
- it 'returns a Hash with all of the node\'s properties' do
+ it "returns a Hash with all of the node's properties" do
expect(subject.view).to eq(node_data)
end
end
@@ -188,7 +188,7 @@ describe Chef::Knife::NodeEditor do
subject.edit_node
end
- it 'returns an array of property names that doesn\'t include ' +
+ it "returns an array of property names that doesn't include " +
"the non-editable properties" do
expect(subject.updated?).to eql %w{ normal policy_name policy_group run_list }
end
diff --git a/spec/unit/knife/data_bag_create_spec.rb b/spec/unit/knife/data_bag_create_spec.rb
index b7d185a58c..169c6e1845 100644
--- a/spec/unit/knife/data_bag_create_spec.rb
+++ b/spec/unit/knife/data_bag_create_spec.rb
@@ -46,8 +46,8 @@ describe Chef::Knife::DataBagCreate do
allow(knife).to receive(:config).and_return(config)
end
- context "when data_bag already exist" do
- it "doesn't creates a data bag" do
+ context "when data_bag already exists" do
+ it "doesn't create a data bag" do
expect(knife).to receive(:create_object).and_yield(raw_hash)
expect(rest).to receive(:get).with("data/#{bag_name}")
expect(rest).to_not receive(:post).with("data", { "name" => bag_name })
@@ -72,6 +72,35 @@ describe Chef::Knife::DataBagCreate do
expect { knife.run }.to exit_with_code(1)
end
+ it "won't create a data bag with a reserved name for search" do
+ %w{node role client environment}.each do |name|
+ knife.name_args = [name]
+ expect(Chef::DataBag).to receive(:validate_name!).with(knife.name_args[0]).and_raise(Chef::Exceptions::InvalidDataBagName)
+ expect { knife.run }.to exit_with_code(1)
+ end
+ end
+
+ context "when part of the name is a reserved name" do
+ before do
+ exception = double("404 error", :code => "404")
+ %w{node role client environment}.each do |name|
+ allow(rest).to receive(:get)
+ .with("data/sudoing_#{name}_admins")
+ .and_raise(Net::HTTPServerException.new("404", exception))
+ end
+ end
+
+ it "will create a data bag containing a reserved word" do
+ %w{node role client environment}.each do |name|
+ knife.name_args = ["sudoing_#{name}_admins"]
+ expect(rest).to receive(:post).with("data", { "name" => knife.name_args[0] })
+ expect(knife.ui).to receive(:info).with("Created data_bag[#{knife.name_args[0]}]")
+
+ knife.run
+ end
+ end
+ end
+
context "when given one argument" do
before do
knife.name_args = [bag_name]
@@ -85,6 +114,23 @@ describe Chef::Knife::DataBagCreate do
end
end
+ context "when given a data bag name partially matching a reserved name for search" do
+ %w{xnode rolex xenvironmentx xclientx}.each do |name|
+ let(:bag_name) { name }
+
+ before do
+ knife.name_args = [bag_name]
+ end
+
+ it "creates a data bag named '#{name}'" do
+ expect(rest).to receive(:post).with("data", { "name" => bag_name })
+ expect(knife.ui).to receive(:info).with("Created data_bag[#{bag_name}]")
+
+ knife.run
+ end
+ end
+ end
+
context "no secret is specified for encryption" do
let(:item) do
item = Chef::DataBagItem.from_hash(raw_hash)
diff --git a/spec/unit/knife/data_bag_show_spec.rb b/spec/unit/knife/data_bag_show_spec.rb
index ece7f5bf78..8dd0669993 100644
--- a/spec/unit/knife/data_bag_show_spec.rb
+++ b/spec/unit/knife/data_bag_show_spec.rb
@@ -91,12 +91,11 @@ qux: http://localhost:4000/data/bag_o_data/qux}
context "Data bag to show is not encrypted" do
before do
allow(knife).to receive(:encrypted?).and_return(false)
- expect(knife).to receive(:read_secret).exactly(0).times
end
it "displays the data bag" do
+ expect(knife).to receive(:read_secret).exactly(0).times
expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(data_bag)
- expect(knife.ui).to receive(:warn).with("Unencrypted data bag detected, ignoring any provided secret options.")
expected = %q{baz: http://localhost:4000/data/bag_o_data/baz
id: id
@@ -104,6 +103,21 @@ qux: http://localhost:4000/data/bag_o_data/qux}
knife.run
expect(stdout.string.strip).to eq(expected)
end
+
+ context "when a secret is given" do
+ it "displays the data bag" do
+ expect(knife).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(true)
+ expect(knife).to receive(:read_secret).and_return(secret)
+ expect(Chef::DataBagItem).to receive(:load).with(bag_name, item_name).and_return(data_bag)
+ expect(knife.ui).to receive(:warn).with("Unencrypted data bag detected, ignoring any provided secret options.")
+
+ expected = %q{baz: http://localhost:4000/data/bag_o_data/baz
+id: id
+qux: http://localhost:4000/data/bag_o_data/qux}
+ knife.run
+ expect(stdout.string.strip).to eq(expected)
+ end
+ end
end
it "displays the list of items in the data bag when only one @name_arg is provided" do
diff --git a/spec/unit/knife/environment_compare_spec.rb b/spec/unit/knife/environment_compare_spec.rb
index e408532884..82960f3db3 100644
--- a/spec/unit/knife/environment_compare_spec.rb
+++ b/spec/unit/knife/environment_compare_spec.rb
@@ -61,7 +61,7 @@ describe Chef::Knife::EnvironmentCompare do
it "should display only cookbooks with version constraints" do
@knife.config[:format] = "summary"
@knife.run
- @environments.each do |item, url|
+ @environments.each_key do |item|
expect(@stdout.string).to(match /#{item}/) && expect(@stdout.string.lines.count).to(be 4)
end
end
@@ -78,7 +78,7 @@ describe Chef::Knife::EnvironmentCompare do
@knife.config[:format] = "summary"
@knife.config[:mismatch] = true
@knife.run
- @constraints.each do |item, ver|
+ @constraints.each_value do |ver|
expect(@stdout.string).to match /#{ver[1]}/
end
end
@@ -96,7 +96,7 @@ describe Chef::Knife::EnvironmentCompare do
@knife.config[:format] = "summary"
@knife.config[:all] = true
@knife.run
- @constraints.each do |item, ver|
+ @constraints.each_value do |ver|
expect(@stdout.string).to match /#{ver[1]}/
end
end
diff --git a/spec/unit/knife/index_rebuild_spec.rb b/spec/unit/knife/index_rebuild_spec.rb
deleted file mode 100644
index 97a3a69155..0000000000
--- a/spec/unit/knife/index_rebuild_spec.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-
-describe Chef::Knife::IndexRebuild do
-
- let(:knife) { Chef::Knife::IndexRebuild.new }
- let(:rest_client) { double(Chef::ServerAPI) }
-
- let(:stub_rest!) do
- expect(knife).to receive(:rest).and_return(rest_client)
- end
-
- before :each do
- # This keeps the test output clean
- allow(knife.ui).to receive(:stdout).and_return(StringIO.new)
- end
-
- context "#grab_api_info" do
- let(:http_not_found_response) do
- e = Net::HTTPNotFound.new("1.1", 404, "blah")
- allow(e).to receive(:[]).with("x-ops-api-info").and_return(api_header_value)
- e
- end
-
- let(:http_server_exception) do
- Net::HTTPServerException.new("404: Not Found", http_not_found_response)
- end
-
- before(:each) do
- stub_rest!
- allow(rest_client).to receive(:get).and_raise(http_server_exception)
- end
-
- context "against a Chef 11 server" do
- let(:api_header_value) { "flavor=osc;version=11.0.0;erchef=1.2.3" }
- it "retrieves API information" do
- expect(knife.grab_api_info).to eq({ "flavor" => "osc", "version" => "11.0.0", "erchef" => "1.2.3" })
- end
- end # Chef 11
-
- context "against a Chef 10 server" do
- let(:api_header_value) { nil }
- it "finds no API information" do
- expect(knife.grab_api_info).to eq({})
- end
- end # Chef 10
- end # grab_api_info
-
- context "#unsupported_version?" do
- context "with Chef 11 API metadata" do
- it "is unsupported" do
- expect(knife.unsupported_version?({ "version" => "11.0.0", "flavor" => "osc", "erchef" => "1.2.3" })).to be_truthy
- end
-
- it "only truly relies on the version being non-nil" do
- expect(knife.unsupported_version?({ "version" => "1", "flavor" => "osc", "erchef" => "1.2.3" })).to be_truthy
- end
- end
-
- context "with Chef 10 API metadata" do
- it "is supported" do
- # Chef 10 will have no metadata
- expect(knife.unsupported_version?({})).to be_falsey
- end
- end
- end # unsupported_version?
-
- context "Simulating a 'knife index rebuild' run" do
-
- before :each do
- expect(knife).to receive(:grab_api_info).and_return(api_info)
- server_specific_stubs!
- end
-
- context "against a Chef 11 server" do
- let(:api_info) do
- { "flavor" => "osc",
- "version" => "11.0.0",
- "erchef" => "1.2.3",
- }
- end
- let(:server_specific_stubs!) do
- expect(knife).to receive(:unsupported_server_message).with(api_info)
- expect(knife).to receive(:exit).with(1)
- end
-
- it "should not be allowed" do
- knife.run
- end
- end
-
- context "against a Chef 10 server" do
- let(:api_info) { {} }
- let(:server_specific_stubs!) do
- stub_rest!
- expect(rest_client).to receive(:post).with("/search/reindex", {}).and_return("representative output")
- expect(knife).not_to receive(:unsupported_server_message)
- expect(knife).to receive(:deprecated_server_message)
- expect(knife).to receive(:nag)
- expect(knife).to receive(:output).with("representative output")
- end
- it "should be allowed" do
- knife.run
- end
- end
- end
-
-end
diff --git a/spec/unit/knife/node_policy_set_spec.rb b/spec/unit/knife/node_policy_set_spec.rb
new file mode 100644
index 0000000000..35306937d8
--- /dev/null
+++ b/spec/unit/knife/node_policy_set_spec.rb
@@ -0,0 +1,122 @@
+#
+# Author:: Piyush Awasthi (<piyush.awasthi@chef.io>)
+# Copyright:: Copyright 2017-2018, Chef Software Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the License);
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an AS IS BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Knife::NodePolicySet do
+ let(:node) do
+ node = Chef::Node.new()
+ node.name("adam")
+ node.run_list = ["role[base]"]
+ node
+ end
+
+ let(:knife) do
+ Chef::Log.logger = Logger.new(StringIO.new)
+ Chef::Config[:knife][:bootstrap_template] = bootstrap_template unless bootstrap_template.nil?
+ knife_obj = Chef::Knife::NodePolicySet.new(bootstrap_cli_options)
+ knife_obj.merge_configs
+ allow(knife_obj.ui).to receive(:stderr).and_return(stderr)
+ allow(knife_obj).to receive(:encryption_secret_provided_ignore_encrypt_flag?).and_return(false)
+ knife_obj
+ end
+
+ let(:stderr) { StringIO.new }
+ let(:bootstrap_template) { nil }
+ let(:bootstrap_cli_options) { [ ] }
+
+ describe "#run" do
+ context "when node_name is not given" do
+ let(:bootstrap_cli_options) { %w{ } }
+ it "returns an error that you must specify a node name" do
+ expect { knife.send(:validate_node!) }.to raise_error(SystemExit)
+ expect(stderr.string).to include("ERROR: You must specify a node name")
+ end
+ end
+
+ context "when node is given" do
+ let(:bootstrap_cli_options) { %w{ adam staging my-app } }
+ it "should load the node" do
+ expect(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node)
+ allow(node).to receive(:save).and_return(true)
+ knife.run
+ end
+ end
+
+ context "when node not saved" do
+ let(:bootstrap_cli_options) { %w{ adam staging my-app } }
+ it "returns an error node not updated successfully" do
+ allow(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node)
+ allow(node).to receive(:save).and_return(false)
+ knife.run
+ expect(stderr.string.strip).to eq("Error in updating node #{node.name}")
+ end
+ end
+
+ context "when the policy is set successfully on the node" do
+ let(:bootstrap_cli_options) { %w{ adam staging my-app } }
+ it "returns node updated successfully" do
+ allow(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node)
+ allow(node).to receive(:save).and_return(true)
+ knife.run
+ expect(stderr.string.strip).to eq("Successfully set the policy on node #{node.name}")
+ end
+ end
+ end
+
+ describe "handling policy options" do
+ context "when policy_group and policy_name is not given" do
+ let(:bootstrap_cli_options) { %w{ } }
+ it "returns an error stating that policy_name and policy_group must be given together" do
+ expect { knife.send(:validate_options!) }.to raise_error(SystemExit)
+ expect(stderr.string).to include("ERROR: Policy group and name must be specified together")
+ end
+ end
+
+ context "when only policy_name is given" do
+ let(:bootstrap_cli_options) { %w{ adam staging } }
+ it "returns an error stating that policy_name and policy_group must be given together" do
+ expect { knife.send(:validate_options!) }.to raise_error(SystemExit)
+ expect(stderr.string).to include("ERROR: Policy group and name must be specified together")
+ end
+ end
+
+ context "when only policy_group is given" do
+ let(:bootstrap_cli_options) { %w{ adam my-app } }
+ it "returns an error stating that policy_name and policy_group must be given together" do
+ expect { knife.send(:validate_options!) }.to raise_error(SystemExit)
+ expect(stderr.string).to include("ERROR: Policy group and name must be specified together")
+ end
+ end
+
+ context "when policy_name and policy_group are given with no conflicting options" do
+ let(:bootstrap_cli_options) { %w{ adam staging my-app } }
+ it "passes options validation" do
+ expect { knife.send(:validate_options!) }.to_not raise_error
+ end
+
+ it "returns value set in config" do
+ allow(Chef::Node).to receive(:load).with(bootstrap_cli_options[0]).and_return(node)
+ allow(node).to receive(:save).and_return(false)
+ knife.run
+ expect(node.policy_name).to eq("my-app")
+ expect(node.policy_group).to eq("staging")
+ end
+ end
+ end
+end
diff --git a/spec/unit/knife/ssh_spec.rb b/spec/unit/knife/ssh_spec.rb
index e15ca8a7f0..af54115ac7 100644
--- a/spec/unit/knife/ssh_spec.rb
+++ b/spec/unit/knife/ssh_spec.rb
@@ -49,28 +49,36 @@ describe Chef::Knife::Ssh do
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"
+ @node_bar["target"] = "10.0.0.2"
+ @node_foo["target"] = "10.0.0.1"
+ @node_bar["prefix"] = "bar"
+ @node_foo["prefix"] = "foo"
+ @knife.config[:ssh_attribute] = "ipaddress"
+ @knife.config[:prefix_attribute] = "name"
Chef::Config[:knife][:ssh_attribute] = "ipaddress" # this value will be in the config file
- expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil], ["10.0.0.2", nil]])
+ Chef::Config[:knife][:prefix_attribute] = "name" # this value will be in the config file
+ expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil, "foo"], ["10.0.0.2", nil, "bar"]])
@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"
+ @node_bar["target"] = "10.0.0.2"
+ @node_foo["target"] = "10.0.0.1"
+ @node_bar["prefix"] = "bar"
+ @node_foo["prefix"] = "foo"
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
- expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil], ["10.0.0.2", nil]])
+ Chef::Config[:knife][:prefix_attribute] = "config_file" # this value will be in the config file
+ @knife.config[:ssh_attribute] = "ipaddress" # this is the value of the command line via #configure_attribute
+ @knife.config[:prefix_attribute] = "name" # this is the value of the command line via #configure_attribute
+ expect(@knife).to receive(:session_from_list).with([["10.0.0.1", nil, "foo"], ["10.0.0.2", nil, "bar"]])
@knife.configure_session
end
end
- it "searchs for and returns an array of fqdns" do
+ it "searches for and returns an array of fqdns" do
expect(@knife).to receive(:session_from_list).with([
- ["foo.example.org", nil],
- ["bar.example.org", nil],
+ ["foo.example.org", nil, nil],
+ ["bar.example.org", nil, nil],
])
@knife.configure_session
end
@@ -84,8 +92,8 @@ describe Chef::Knife::Ssh do
end
it "returns an array of cloud public hostnames" do
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],
+ ["ec2-10-0-0-1.compute-1.amazonaws.com", nil, nil],
+ ["ec2-10-0-0-2.compute-1.amazonaws.com", nil, nil],
])
@knife.configure_session
end
@@ -101,8 +109,8 @@ describe Chef::Knife::Ssh do
it "returns an array of fqdns" do
expect(@knife).to receive(:session_from_list).with([
- ["foo.example.org", nil],
- ["bar.example.org", nil],
+ ["foo.example.org", nil, nil],
+ ["bar.example.org", nil, nil],
])
@knife.configure_session
end
@@ -144,15 +152,35 @@ describe Chef::Knife::Ssh do
end
end
+ describe "#get_prefix_attribute" do
+ # Order of precedence for prefix
+ # 1) config value (cli or knife config)
+ # 2) nil
+ before do
+ Chef::Config[:knife][:prefix_attribute] = nil
+ @knife.config[:prefix_attribute] = nil
+ @node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com"
+ @node_bar["cloud"]["public_hostname"] = ""
+ end
+
+ it "should return nil by default" do
+ expect(@knife.get_prefix_attribute({})).to eq(nil)
+ end
+
+ it "should favor config over nil" do
+ @node_foo["prefix"] = "config"
+ expect( @knife.get_prefix_attribute(@node_foo)).to eq("config")
+ end
+ end
+
describe "#get_ssh_attribute" do
# Order of precedence for ssh target
- # 1) command line attribute
- # 2) configuration file
- # 3) cloud attribute
- # 4) fqdn
+ # 1) config value (cli or knife config)
+ # 2) cloud attribute
+ # 3) fqdn
before do
Chef::Config[:knife][:ssh_attribute] = nil
- @knife.config[:attribute] = nil
+ @knife.config[:ssh_attribute] = nil
@node_foo["cloud"]["public_hostname"] = "ec2-10-0-0-1.compute-1.amazonaws.com"
@node_bar["cloud"]["public_hostname"] = ""
end
@@ -165,18 +193,9 @@ describe Chef::Knife::Ssh do
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")
+ it "should favor config over cloud and default" do
+ @node_foo["target"] = "config"
+ expect( @knife.get_ssh_attribute(@node_foo)).to eq("config")
end
it "should return fqdn if cloud.hostname is empty" do
@@ -192,40 +211,50 @@ describe Chef::Knife::Ssh do
end
it "uses the port from an ssh config file" do
- @knife.session_from_list([["the.b.org", nil]])
+ @knife.session_from_list([["the.b.org", nil, nil]])
expect(@knife.session.servers[0].port).to eq(23)
end
it "uses the port from a cloud attr" do
- @knife.session_from_list([["the.b.org", 123]])
+ @knife.session_from_list([["the.b.org", 123, nil]])
expect(@knife.session.servers[0].port).to eq(123)
end
+ it "uses the prefix from list" do
+ @knife.session_from_list([["the.b.org", nil, "b-team"]])
+ expect(@knife.session.servers[0][:prefix]).to eq("b-team")
+ end
+
+ it "defaults to a prefix of host" do
+ @knife.session_from_list([["the.b.org", nil, nil]])
+ expect(@knife.session.servers[0][:prefix]).to eq("the.b.org")
+ end
+
it "defaults to a timeout of 120 seconds" do
- @knife.session_from_list([["the.b.org", nil]])
+ @knife.session_from_list([["the.b.org", nil, nil]])
expect(@knife.session.servers[0].options[:timeout]).to eq(120)
end
it "uses the timeout from Chef Config" do
Chef::Config[:knife][:ssh_timeout] = 5
@knife.config[:ssh_timeout] = nil
- @knife.session_from_list([["the.b.org", nil]])
+ @knife.session_from_list([["the.b.org", nil, nil]])
expect(@knife.session.servers[0].options[:timeout]).to eq(5)
end
it "uses the timeout from knife config" do
@knife.config[:ssh_timeout] = 6
- @knife.session_from_list([["the.b.org", nil]])
+ @knife.session_from_list([["the.b.org", nil, nil]])
expect(@knife.session.servers[0].options[:timeout]).to eq(6)
end
it "uses the user from an ssh config file" do
- @knife.session_from_list([["the.b.org", 123]])
+ @knife.session_from_list([["the.b.org", 123, nil]])
expect(@knife.session.servers[0].user).to eq("locutus")
end
it "uses keepalive settings from an ssh config file" do
- @knife.session_from_list([["the.b.org", 123]])
+ @knife.session_from_list([["the.b.org", 123, nil]])
expect(@knife.session.servers[0].options[:keepalive]).to be true
expect(@knife.session.servers[0].options[:keepalive_interval]).to eq 60
end
@@ -295,6 +324,23 @@ describe Chef::Knife::Ssh do
end
end
+ describe "#tmux" do
+ before do
+ ssh_config = { :timeout => 50, :user => "locutus", :port => 23, :keepalive => true, :keepalive_interval => 60 }
+ allow(Net::SSH).to receive(:configuration_for).with("foo.example.org", true).and_return(ssh_config)
+ @query = Chef::Search::Query.new
+ expect(@query).to receive(:search).and_yield(@node_foo)
+ allow(Chef::Search::Query).to receive(:new).and_return(@query)
+ allow(@knife).to receive(:exec).and_return(0)
+ end
+
+ it "filters out invalid characters from tmux session name" do
+ @knife.name_args = ["name:foo.example.org", "tmux"]
+ expect(@knife).to receive(:shell_out!).with("tmux new-session -d -s 'knife ssh name=foo-example-org' -n 'foo.example.org' 'ssh locutus@foo.example.org' ")
+ @knife.run
+ end
+ end
+
describe "#run" do
before do
@query = Chef::Search::Query.new
diff --git a/spec/unit/knife_spec.rb b/spec/unit/knife_spec.rb
index 2b22dbc4f7..adaab11d55 100644
--- a/spec/unit/knife_spec.rb
+++ b/spec/unit/knife_spec.rb
@@ -47,6 +47,7 @@ describe Chef::Knife do
allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
allow(config_loader).to receive(:explicit_config_file=)
+ allow(config_loader).to receive(:profile=)
# Prevent gratuitous code reloading:
allow(Chef::Knife).to receive(:load_commands)
@@ -331,6 +332,7 @@ describe Chef::Knife do
knife.config[:config_file] = fake_config
config_loader = double("Chef::WorkstationConfigLoader", :load => true, :no_config_found? => false, :chef_config_dir => "/etc/chef", :config_location => fake_config)
allow(config_loader).to receive(:explicit_config_file=).with(fake_config).and_return(fake_config)
+ allow(config_loader).to receive(:profile=)
allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
end
diff --git a/spec/unit/lwrp_spec.rb b/spec/unit/lwrp_spec.rb
index 75ebbb8f02..009bc5f4b1 100644
--- a/spec/unit/lwrp_spec.rb
+++ b/spec/unit/lwrp_spec.rb
@@ -571,14 +571,16 @@ describe "LWRP" do
context "resource class created" do
let(:test_lwrp_class) { @test_lwrp_class }
- before(:context) do
- @tmpdir = Dir.mktmpdir("lwrp_test")
+ before(:each) do
+ @tmpparent = Dir.mktmpdir("lwrp_test")
+ @tmpdir = File.join(@tmpparent, "lwrp")
+ Dir.mkdir(@tmpdir)
resource_path = File.join(@tmpdir, "once.rb")
IO.write(resource_path, "default_action :create")
@test_lwrp_class = Chef::Resource::LWRPBase.build_from_file("lwrp", resource_path, nil)
end
- after(:context) do
+ after(:each) do
FileUtils.remove_entry @tmpdir
end
diff --git a/spec/unit/mixin/openssl_helper_spec.rb b/spec/unit/mixin/openssl_helper_spec.rb
new file mode 100644
index 0000000000..6873fd8cf2
--- /dev/null
+++ b/spec/unit/mixin/openssl_helper_spec.rb
@@ -0,0 +1,252 @@
+#
+# Copyright 2009-2018, Chef Software, Inc <legal@chef.io>
+#
+# 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/openssl_helper"
+
+describe Chef::Mixin::OpenSSLHelper do
+ let(:instance) do
+ Class.new { include Chef::Mixin::OpenSSLHelper }.new
+ end
+
+ describe ".included" do
+ it "requires openssl" do
+ instance
+ expect(defined?(OpenSSL)).to_not be(false)
+ end
+ end
+
+ # Path helpers
+ describe "#get_key_filename" do
+ context "When the input is not a string" do
+ it "Throws a TypeError" do
+ expect do
+ instance.get_key_filename(33)
+ end.to raise_error(TypeError)
+ end
+ end
+
+ context "when the input is a string" do
+ it "Generates valid keyfile names" do
+ expect(instance.get_key_filename("/etc/temp.crt")).to match("/etc/temp.key")
+ end
+ end
+ end
+
+ # Validation helpers
+ describe "#key_length_valid?" do
+ context "When the number is less than 1024" do
+ it "returns false" do
+ expect(instance.key_length_valid?(1023)).to be_falsey
+ expect(instance.key_length_valid?(2)).to be_falsey
+ expect(instance.key_length_valid?(64)).to be_falsey
+ expect(instance.key_length_valid?(512)).to be_falsey
+ end
+ end
+
+ context "When the number is greater than 1024 but is not a power of 2" do
+ it "returns false" do
+ expect(instance.key_length_valid?(1025)).to be_falsey
+ expect(instance.key_length_valid?(6666)).to be_falsey
+ expect(instance.key_length_valid?(8191)).to be_falsey
+ end
+ end
+
+ context "When the number is a power of 2, equal to or greater than 1024" do
+ it "returns true" do
+ expect(instance.key_length_valid?(1024)).to be_truthy
+ expect(instance.key_length_valid?(2048)).to be_truthy
+ expect(instance.key_length_valid?(4096)).to be_truthy
+ expect(instance.key_length_valid?(8192)).to be_truthy
+ end
+ end
+ end
+
+ describe "#dhparam_pem_valid?" do
+ require "tempfile"
+
+ before(:each) do
+ @dhparam_file = Tempfile.new("dhparam")
+ end
+
+ context "When the dhparam.pem file does not exist" do
+ it "returns false" do
+ expect(instance.dhparam_pem_valid?("/tmp/bad_filename")).to be_falsey
+ end
+ end
+
+ context "When the dhparam.pem file does exist, but does not contain a valid dhparam key" do
+ it "Throws an OpenSSL::PKey::DHError exception" do
+ expect do
+ @dhparam_file.puts("I_am_not_a_key_I_am_a_free_man")
+ @dhparam_file.close
+ instance.dhparam_pem_valid?(@dhparam_file.path)
+ end.to raise_error(::OpenSSL::PKey::DHError)
+ end
+ end
+
+ context "When the dhparam.pem file does exist, and does contain a vaild dhparam key" do
+ it "returns true" do
+ @dhparam_file.puts(::OpenSSL::PKey::DH.new(1024).to_pem)
+ @dhparam_file.close
+ expect(instance.dhparam_pem_valid?(@dhparam_file.path)).to be_truthy
+ end
+ end
+
+ after(:each) do
+ @dhparam_file.unlink
+ end
+ end
+
+ describe "#priv_key_file_valid?" do
+ require "tempfile"
+ require "openssl" unless defined?(OpenSSL)
+
+ cipher = ::OpenSSL::Cipher.new("des3")
+
+ before(:each) do
+ @keyfile = Tempfile.new("keyfile")
+ end
+
+ context "When the key file does not exist" do
+ it "returns false" do
+ expect(instance.priv_key_file_valid?("/tmp/bad_filename")).to be_falsey
+ end
+ end
+
+ context "When the key file does exist, but does not contain a valid rsa private key" do
+ it "Throws an OpenSSL::PKey::RSAError exception" do
+ @keyfile.write("I_am_not_a_key_I_am_a_free_man")
+ @keyfile.close
+ expect(instance.priv_key_file_valid?(@keyfile.path)).to be_falsey
+ end
+ end
+
+ context "When the key file does exist, and does contain a vaild rsa private key" do
+ it "returns true" do
+ @keyfile.write(::OpenSSL::PKey::RSA.new(1024).to_pem)
+ @keyfile.close
+ expect(instance.priv_key_file_valid?(@keyfile.path)).to be_truthy
+ end
+ end
+
+ context "When a valid keyfile requires a passphrase, and an invalid passphrase is supplied" do
+ it "returns false" do
+ @keyfile.write(::OpenSSL::PKey::RSA.new(1024).to_pem(cipher, "oink"))
+ @keyfile.close
+ expect(instance.priv_key_file_valid?(@keyfile.path, "poml")).to be_falsey
+ end
+ end
+
+ context "When a valid keyfile requires a passphrase, and a valid passphrase is supplied" do
+ it "returns true" do
+ @keyfile.write(::OpenSSL::PKey::RSA.new(1024).to_pem(cipher, "oink"))
+ @keyfile.close
+ expect(instance.priv_key_file_valid?(@keyfile.path, "oink")).to be_truthy
+ end
+ end
+
+ after(:each) do
+ @keyfile.unlink
+ end
+ end
+
+ # Generators
+ describe "#gen_dhparam" do
+ context "When given an invalid key length" do
+ it "Throws an ArgumentError" do
+ expect do
+ instance.gen_dhparam(2046, 2)
+ end.to raise_error(ArgumentError)
+ end
+ end
+
+ context "When given an invalid generator id" do
+ it "Throws a TypeError" do
+ expect do
+ instance.gen_dhparam(2048, "bob")
+ end.to raise_error(TypeError)
+ end
+ end
+
+ context "When a proper key length and generator id are given" do
+ it "Generates a dhparam object" do
+ expect(instance.gen_dhparam(1024, 2)).to be_kind_of(::OpenSSL::PKey::DH)
+ end
+ end
+ end
+
+ describe "#gen_rsa_priv_key" do
+ context "When given an invalid key length" do
+ it "Throws an ArgumentError" do
+ expect do
+ instance.gen_rsa_priv_key(4093)
+ end.to raise_error(ArgumentError)
+ end
+ end
+
+ context "When a proper key length is given" do
+ it "Generates an RSA key object" do
+ expect(instance.gen_rsa_priv_key(1024)).to be_kind_of(::OpenSSL::PKey::RSA)
+ end
+ end
+ end
+
+ describe "#encrypt_rsa_key" do
+ before(:all) do
+ @rsa_key = ::OpenSSL::PKey::RSA.new(1024)
+ end
+
+ context "When given anything other than an RSA key object to encrypt" do
+ it "Raises a TypeError" do
+ expect do
+ instance.encrypt_rsa_key("abcd", "efgh", "des3")
+ end.to raise_error(TypeError)
+ end
+ end
+
+ context "When given anything other than a string as the passphrase" do
+ it "Raises a TypeError" do
+ expect do
+ instance.encrypt_rsa_key(@rsa_key, 1234, "des3")
+ end.to raise_error(TypeError)
+ end
+ end
+
+ context "When given anything other than a string as the cipher" do
+ it "Raises a TypeError" do
+ expect do
+ instance.encrypt_rsa_key(@rsa_key, "1234", 1234)
+ end.to raise_error(TypeError)
+ end
+ end
+
+ context "When given an invalid cipher string" do
+ it "Raises an ArgumentError" do
+ expect do
+ instance.encrypt_rsa_key(@rsa_key, "1234", "des3_bogus")
+ end.to raise_error(ArgumentError)
+ end
+ end
+
+ context "When given a valid RSA key and a valid passphrase string" do
+ it "Generates a valid encrypted PEM" do
+ @encrypted_key = instance.encrypt_rsa_key(@rsa_key, "oink", "des3")
+ expect(@encrypted_key).to be_kind_of(String)
+ expect(::OpenSSL::PKey::RSA.new(@encrypted_key, "oink").private?).to be_truthy
+ end
+ end
+ end
+end
diff --git a/spec/unit/mixin/params_validate_spec.rb b/spec/unit/mixin/params_validate_spec.rb
index 0cafb925c8..7bc8a27398 100644
--- a/spec/unit/mixin/params_validate_spec.rb
+++ b/spec/unit/mixin/params_validate_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2016, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -342,6 +342,17 @@ describe Chef::Mixin::ParamsValidate do
end.to raise_error(Chef::Exceptions::ValidationFailed)
end
+ it "allows a custom validation message" do
+ expect do
+ @vo.validate({ :not_blank => "should pass" },
+ { :not_blank => { :cannot_be => [ :nil, :empty ], validation_message: "my validation message" } })
+ end.not_to raise_error
+ expect do
+ @vo.validate({ :not_blank => "" },
+ { :not_blank => { :cannot_be => [ :nil, :empty ], validation_message: "my validation message" } })
+ end.to raise_error(Chef::Exceptions::ValidationFailed, "my validation message")
+ end
+
it "should set and return a value, then return the same value" do
value = "meow"
expect(@vo.set_or_return(:test, value, {}).object_id).to eq(value.object_id)
diff --git a/spec/unit/mixin/powershell_type_coercions_spec.rb b/spec/unit/mixin/powershell_type_coercions_spec.rb
index 6f52abccfb..159a0a8d1d 100644
--- a/spec/unit/mixin/powershell_type_coercions_spec.rb
+++ b/spec/unit/mixin/powershell_type_coercions_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Jay Mundrawala (<jdm@chef.io>)
-# Copyright:: Copyright 2015-2016, Chef Software, Inc.
+# Copyright:: Copyright 2015-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -64,14 +64,15 @@ describe Chef::Mixin::PowershellTypeCoercions do
end
it "translates a Chef::Node::ImmutableMash like a hash" do
- test_mash = Chef::Node::ImmutableMash.new({ "a" => 1, "b" => 1.2,
- "c" => false, "d" => true })
- expect(test_class.translate_type(test_mash)).to eq("@{a=1;b=1.2;c=$false;d=$true}")
+ node = Chef::Node.new
+ node.default[:test] = { "a" => 1, "b" => 1.2, "c" => false, "d" => true }
+ expect(test_class.translate_type(node[:test])).to eq("@{a=1;b=1.2;c=$false;d=$true}")
end
it "translates a Chef::Node::ImmutableArray like an array" do
- test_array = Chef::Node::ImmutableArray.new([true, false])
- expect(test_class.translate_type(test_array)).to eq("@($true,$false)")
+ node = Chef::Node.new
+ node.default[:test] = [ true, false ]
+ expect(test_class.translate_type(node[:test])).to eq("@($true,$false)")
end
it "falls back :to_psobject if we have not defined at explicit rule" do
diff --git a/spec/unit/mixin/properties_spec.rb b/spec/unit/mixin/properties_spec.rb
index 1af0bc7abd..ee0c252381 100644
--- a/spec/unit/mixin/properties_spec.rb
+++ b/spec/unit/mixin/properties_spec.rb
@@ -11,6 +11,7 @@ module ChefMixinPropertiesSpec
property :a, "a", default: "a"
property :ab, %w{a b}, default: "a"
property :ac, %w{a c}, default: "a"
+ property :d, "d", description: "The d property", introduced: "14.0"
end
context "and a module B with properties b, ab and bc" do
@@ -30,11 +31,20 @@ module ChefMixinPropertiesSpec
end
it "A.properties has a, ab, and ac with types 'a', ['a', 'b'], and ['b', 'c']" do
- expect(A.properties.keys).to eq [ :a, :ab, :ac ]
+ expect(A.properties.keys).to eq [ :a, :ab, :ac, :d ]
expect(A.properties[:a].validation_options[:is]).to eq "a"
expect(A.properties[:ab].validation_options[:is]).to eq %w{a b}
expect(A.properties[:ac].validation_options[:is]).to eq %w{a c}
end
+
+ it "A.properties can get the description of `d`" do
+ expect(A.properties[:d].description).to eq "The d property"
+ end
+
+ it "A.properties can get the release that introduced `d`" do
+ expect(A.properties[:d].introduced).to eq "14.0"
+ end
+
it "B.properties has b, ab, and bc with types 'b', nil and ['b', 'c']" do
expect(B.properties.keys).to eq [ :b, :ab, :bc ]
expect(B.properties[:b].validation_options[:is]).to eq "b"
@@ -42,7 +52,7 @@ module ChefMixinPropertiesSpec
expect(B.properties[:bc].validation_options[:is]).to eq %w{b c}
end
it "C.properties has a, b, c, ac and bc with merged types" do
- expect(C.properties.keys).to eq [ :a, :ab, :ac, :b, :bc, :c ]
+ expect(C.properties.keys).to eq [ :a, :ab, :ac, :d, :b, :bc, :c ]
expect(C.properties[:a].validation_options[:is]).to eq "a"
expect(C.properties[:b].validation_options[:is]).to eq "b"
expect(C.properties[:c].validation_options[:is]).to eq "c"
diff --git a/spec/unit/mixin/user_context_spec.rb b/spec/unit/mixin/user_context_spec.rb
index f2119b6dbc..3dadf6a2c3 100644
--- a/spec/unit/mixin/user_context_spec.rb
+++ b/spec/unit/mixin/user_context_spec.rb
@@ -41,7 +41,6 @@ describe "a class that mixes in user_context" do
before do
allow(::Chef::Platform).to receive(:windows?).and_return(true)
allow(::Chef::Util::Windows::LogonSession).to receive(:new).and_return(logon_session)
- allow(instance_with_user_context).to receive(:node).and_return({ "platform_family" => "windows" })
end
let(:logon_session) { instance_double("::Chef::Util::Windows::LogonSession", :set_user_context => nil, :open => nil, :close => nil) }
@@ -99,7 +98,7 @@ describe "a class that mixes in user_context" do
context "when not running on Windows" do
before do
- allow(instance_with_user_context).to receive(:node).and_return({ "platform_family" => "ubuntu" })
+ allow(::Chef::Platform).to receive(:windows?).and_return(false)
end
it "raises a ::Chef::Exceptions::UnsupportedPlatform exception" do
diff --git a/spec/unit/node/attribute_spec.rb b/spec/unit/node/attribute_spec.rb
index cf8d4d4a4f..42cdf2a9ce 100644
--- a/spec/unit/node/attribute_spec.rb
+++ b/spec/unit/node/attribute_spec.rb
@@ -1,7 +1,7 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
# Author:: AJ Christensen (<aj@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -171,6 +171,7 @@ describe Chef::Node::Attribute do
}
@automatic_hash = { "week" => "friday" }
@attributes = Chef::Node::Attribute.new(@attribute_hash, @default_hash, @override_hash, @automatic_hash, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
describe "initialize" do
@@ -179,13 +180,14 @@ describe Chef::Node::Attribute do
end
it "should take an Automatioc, Normal, Default and Override hash" do
- expect { Chef::Node::Attribute.new({}, {}, {}, {}) }.not_to raise_error
+ expect { Chef::Node::Attribute.new({}, {}, {}, {}, node) }.not_to raise_error
end
[ :normal, :default, :override, :automatic ].each do |accessor|
it "should set #{accessor}" do
- na = Chef::Node::Attribute.new({ :normal => true }, { :default => true }, { :override => true }, { :automatic => true })
- expect(na.send(accessor)).to eq({ accessor.to_s => true })
+ @attributes = Chef::Node::Attribute.new({ :normal => true }, { :default => true }, { :override => true }, { :automatic => true }, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
+ expect(@attributes.send(accessor)).to eq({ accessor.to_s => true })
end
end
@@ -330,7 +332,8 @@ describe Chef::Node::Attribute do
end
it "merges nested hashes between precedence levels" do
- @attributes = Chef::Node::Attribute.new({}, {}, {}, {})
+ @attributes = Chef::Node::Attribute.new({}, {}, {}, {}, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
@attributes.env_default = { "a" => { "b" => { "default" => "default" } } }
@attributes.normal = { "a" => { "b" => { "normal" => "normal" } } }
@attributes.override = { "a" => { "override" => "role" } }
@@ -584,13 +587,15 @@ describe Chef::Node::Attribute do
"one" => { "six" => "seven" },
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should yield each top level key" do
collect = Array.new
- @attributes.keys.each do |k|
+ @attributes.each_key do |k|
collect << k
end
expect(collect.include?("one")).to eq(true)
@@ -603,7 +608,7 @@ describe Chef::Node::Attribute do
it "should yield lower if we go deeper" do
collect = Array.new
- @attributes["one"].keys.each do |k|
+ @attributes["one"].each_key do |k|
collect << k
end
expect(collect.include?("two")).to eq(true)
@@ -632,8 +637,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should yield each top level key and value, post merge rules" do
@@ -670,8 +677,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to each_key" do
@@ -706,8 +715,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to each_pair" do
@@ -742,8 +753,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to each_value" do
@@ -786,9 +799,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
- @empty = Chef::Node::Attribute.new({}, {}, {}, {})
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to empty?" do
@@ -796,7 +810,9 @@ describe Chef::Node::Attribute do
end
it "should return true when there are no keys" do
- expect(@empty.empty?).to eq(true)
+ @attributes = Chef::Node::Attribute.new({}, {}, {}, {}, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
+ expect(@attributes.empty?).to eq(true)
end
it "should return false when there are keys" do
@@ -820,8 +836,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to fetch" do
@@ -877,8 +895,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to has_value?" do
@@ -922,8 +942,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to index" do
@@ -963,8 +985,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to values" do
@@ -999,8 +1023,10 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
end
it "should respond to select" do
@@ -1049,10 +1075,11 @@ describe Chef::Node::Attribute do
"one" => "six",
"snack" => "cookies",
},
- {}
+ {},
+ node
)
+ allow(node).to receive(:attributes).and_return(@attributes)
- @empty = Chef::Node::Attribute.new({}, {}, {}, {})
end
it "should respond to size" do
@@ -1064,7 +1091,9 @@ describe Chef::Node::Attribute do
end
it "should return 0 for an empty attribute" do
- expect(@empty.size).to eq(0)
+ @attributes = Chef::Node::Attribute.new({}, {}, {}, {}, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
+ expect(@attributes.size).to eq(0)
end
it "should return the number of pairs" do
@@ -1092,8 +1121,9 @@ describe Chef::Node::Attribute do
describe "to_s" do
it "should output simple attributes" do
- attributes = Chef::Node::Attribute.new(nil, nil, nil, nil)
- expect(attributes.to_s).to eq("{}")
+ @attributes = Chef::Node::Attribute.new(nil, nil, nil, nil, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
+ expect(@attributes.to_s).to eq("{}")
end
it "should output merged attributes" do
@@ -1105,8 +1135,9 @@ describe Chef::Node::Attribute do
"b" => 3,
"c" => 4,
}
- attributes = Chef::Node::Attribute.new(nil, default_hash, override_hash, nil)
- expect(attributes.to_s).to eq('{"a"=>1, "b"=>3, "c"=>4}')
+ @attributes = Chef::Node::Attribute.new(nil, default_hash, override_hash, nil, node)
+ allow(node).to receive(:attributes).and_return(@attributes)
+ expect(@attributes.to_s).to eq('{"b"=>3, "c"=>4, "a"=>1}')
end
end
@@ -1273,4 +1304,19 @@ describe Chef::Node::Attribute do
expect { @attributes["foo"]["bar"][0] << "buzz" }.to raise_error(RuntimeError, "can't modify frozen String")
end
end
+
+ describe "assigning lazy ungenerated caches to other attributes" do
+ it "works with arrays" do
+ @attributes.default["foo"]["baz"] = %w{one two}
+ @attributes.default["bar"]["baz"] = @attributes["foo"]["baz"]
+ expect(@attributes.default["bar"]["baz"]).to eql(%w{one two})
+ end
+
+ it "works with hashes" do
+ @attributes.default["foo"]["baz"] = { "one" => "two" }
+ @attributes.default["bar"]["baz"] = @attributes["foo"]["baz"]
+ expect(@attributes.default["bar"]["baz"]).to eql({ "one" => "two" })
+ end
+ end
+
end
diff --git a/spec/unit/node/immutable_collections_spec.rb b/spec/unit/node/immutable_collections_spec.rb
index 2d3392041c..29ae8799e9 100644
--- a/spec/unit/node/immutable_collections_spec.rb
+++ b/spec/unit/node/immutable_collections_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Daniel DeLeo (<dan@chef.io>)
-# Copyright:: Copyright 2012-2017, Chef Software Inc.
+# Copyright:: Copyright 2012-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,13 +20,23 @@ require "spec_helper"
require "chef/node/immutable_collections"
describe Chef::Node::ImmutableMash do
+
before do
- @data_in = { "top" => { "second_level" => "some value" },
- "top_level_2" => %w{array of values},
- "top_level_3" => [{ "hash_array" => 1, "hash_array_b" => 2 }],
- "top_level_4" => { "level2" => { "key" => "value" } },
+ @data_in = { "key" =>
+ { "top" => { "second_level" => "some value" },
+ "top_level_2" => %w{array of values},
+ "top_level_3" => [{ "hash_array" => 1, "hash_array_b" => 2 }],
+ "top_level_4" => { "level2" => { "key" => "value" } },
+ },
}
- @immutable_mash = Chef::Node::ImmutableMash.new(@data_in)
+ @node = Chef::Node.new()
+ @node.attributes.default = @data_in
+ @immutable_mash = @node["key"]
+ end
+
+ it "does not have any unaudited methods" do
+ unaudited_methods = Hash.instance_methods - Object.instance_methods - Chef::Node::Mixin::ImmutablizeHash::DISALLOWED_MUTATOR_METHODS - Chef::Node::Mixin::ImmutablizeHash::ALLOWED_METHODS
+ expect(unaudited_methods).to be_empty
end
it "element references like regular hash" do
@@ -57,9 +67,9 @@ describe Chef::Node::ImmutableMash do
# we only ever absorb VividMashes from other precedence levels, which already have
# been coerced to only have string keys, so we do not need to do that work twice (performance).
it "does not call convert_value like Mash/VividMash" do
- @mash = Chef::Node::ImmutableMash.new({ test: "foo", "test2" => "bar" })
- expect(@mash[:test]).to eql("foo")
- expect(@mash["test2"]).to eql("bar")
+ @node.attributes.default = { test: "foo", "test2" => "bar" }
+ expect(@node[:test]).to eql("foo")
+ expect(@node["test2"]).to eql("bar")
end
describe "to_hash" do
@@ -80,7 +90,7 @@ describe Chef::Node::ImmutableMash do
end
it "should create a mash with the same content" do
- expect(@copy).to eq(@immutable_mash)
+ expect(@copy).to eql(@immutable_mash)
end
it "should allow mutation" do
@@ -175,9 +185,11 @@ end
describe Chef::Node::ImmutableArray do
before do
- @immutable_array = Chef::Node::ImmutableArray.new(%w{foo bar baz} + Array(1..3) + [nil, true, false, [ "el", 0, nil ] ])
- immutable_mash = Chef::Node::ImmutableMash.new({ "m" => "m" })
- @immutable_nested_array = Chef::Node::ImmutableArray.new(["level1", @immutable_array, immutable_mash])
+ @node = Chef::Node.new()
+ @node.attributes.default = { "key" => ["level1", %w{foo bar baz} + Array(1..3) + [nil, true, false, [ "el", 0, nil ] ], { "m" => "m" }] }
+ @immutable_array = @node["key"][1]
+ @immutable_mash = @node["key"][2]
+ @immutable_nested_array = @node["key"]
end
##
@@ -221,6 +233,11 @@ describe Chef::Node::ImmutableArray do
end
end
+ it "does not have any unaudited methods" do
+ unaudited_methods = Array.instance_methods - Object.instance_methods - Chef::Node::Mixin::ImmutablizeArray::DISALLOWED_MUTATOR_METHODS - Chef::Node::Mixin::ImmutablizeArray::ALLOWED_METHODS
+ expect(unaudited_methods).to be_empty
+ end
+
it "can be duped even if some elements can't" do
@immutable_array.dup
end
@@ -249,7 +266,7 @@ describe Chef::Node::ImmutableArray do
end
it "should create an array with the same content" do
- expect(@copy).to eq(@immutable_nested_array)
+ expect(@immutable_nested_array).to eq(@copy)
end
it "should allow mutation" do
@@ -301,7 +318,7 @@ describe Chef::Node::ImmutableArray do
end
it "should create an array with the same content" do
- expect(@copy).to eq(@immutable_nested_array)
+ expect(@immutable_nested_array).to eq(@copy)
end
it "should allow mutation" do
@@ -314,4 +331,11 @@ describe Chef::Node::ImmutableArray do
expect(@immutable_array[1, 2]).to eql(%w{bar baz})
end
end
+
+ describe "uniq" do
+ it "works" do
+ @node.attributes.default = { "key" => %w{foo bar foo baz bar} }
+ expect(@node["key"].uniq).to eql(%w{foo bar baz})
+ end
+ end
end
diff --git a/spec/unit/node/vivid_mash_spec.rb b/spec/unit/node/vivid_mash_spec.rb
index 4898c22380..651cfa0058 100644
--- a/spec/unit/node/vivid_mash_spec.rb
+++ b/spec/unit/node/vivid_mash_spec.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2016, Chef Software Inc.
+# Copyright:: Copyright 2016-2017, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -60,7 +60,7 @@ describe Chef::Node::VividMash do
end
it "deep converts values through arrays" do
- expect(root).to receive(:reset_cache).with("foo")
+ expect(root).to receive(:reset_cache).with(no_args)
vivid["foo"] = [ { :bar => true } ]
expect(vivid["foo"].class).to eql(Chef::Node::AttrArray)
expect(vivid["foo"][0].class).to eql(Chef::Node::VividMash)
@@ -68,7 +68,7 @@ describe Chef::Node::VividMash do
end
it "deep converts values through nested arrays" do
- expect(root).to receive(:reset_cache).with("foo")
+ expect(root).to receive(:reset_cache).with(no_args)
vivid["foo"] = [ [ { :bar => true } ] ]
expect(vivid["foo"].class).to eql(Chef::Node::AttrArray)
expect(vivid["foo"][0].class).to eql(Chef::Node::AttrArray)
@@ -77,7 +77,7 @@ describe Chef::Node::VividMash do
end
it "deep converts values through hashes" do
- expect(root).to receive(:reset_cache).with("foo")
+ expect(root).to receive(:reset_cache).with(no_args)
vivid["foo"] = { baz: { :bar => true } }
expect(vivid["foo"]).to be_an_instance_of(Chef::Node::VividMash)
expect(vivid["foo"]["baz"]).to be_an_instance_of(Chef::Node::VividMash)
@@ -184,42 +184,55 @@ describe Chef::Node::VividMash do
it "should deeply autovivify" do
expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five", "six")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five", "six", "seven")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five", "six", "seven", "eight")
vivid.write("one", "five", "six", "seven", "eight", "nine", "ten")
expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
end
it "should raise an exception if you overwrite an array with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect(root).to receive(:reset_cache).at_least(:once).with("array")
vivid.write("array", "five", "six")
expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => "six" }, "nil" => nil })
end
it "should raise an exception if you traverse through an array with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect(root).to receive(:reset_cache).at_least(:once).with("array")
+ expect(root).to receive(:reset_cache).at_least(:once).with("array", "five")
vivid.write("array", "five", "six", "seven")
expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => { "five" => { "six" => "seven" } }, "nil" => nil })
end
it "should raise an exception if you overwrite a string with a hash" do
- expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "two")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "two", "three")
vivid.write("one", "two", "three", "four", "five")
expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => "five" } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
end
it "should raise an exception if you traverse through a string with a hash" do
- expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "two")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "two", "three")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "two", "three", "four")
vivid.write("one", "two", "three", "four", "five", "six")
expect(vivid).to eql({ "one" => { "two" => { "three" => { "four" => { "five" => "six" } } } }, "array" => [ 0, 1, 2 ], "nil" => nil })
end
it "should raise an exception if you overwrite a nil with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect(root).to receive(:reset_cache).at_least(:once).with("nil")
vivid.write("nil", "one", "two")
expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => "two" } })
end
it "should raise an exception if you traverse through a nil with a hash" do
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with("nil", "one")
vivid.write("nil", "one", "two", "three")
expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ], "nil" => { "one" => { "two" => "three" } } })
end
@@ -240,6 +253,10 @@ describe Chef::Node::VividMash do
it "should deeply autovivify" do
expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five", "six")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five", "six", "seven")
+ expect(root).to receive(:reset_cache).at_least(:once).with("one", "five", "six", "seven", "eight")
vivid.write!("one", "five", "six", "seven", "eight", "nine", "ten")
expect(vivid["one"]["five"]["six"]["seven"]["eight"]["nine"]).to eql("ten")
end
@@ -295,7 +312,7 @@ describe Chef::Node::VividMash do
end
it "should unlink hashes" do
- expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect( vivid.unlink("one") ).to eql({ "two" => { "three" => "four" } })
expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
end
@@ -307,7 +324,7 @@ describe Chef::Node::VividMash do
end
it "should unlink nil" do
- expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect(vivid.unlink("nil")).to eql(nil)
expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
end
@@ -327,7 +344,7 @@ describe Chef::Node::VividMash do
end
it "should unlink! hashes" do
- expect(root).to receive(:reset_cache).at_least(:once).with("one")
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect( vivid.unlink!("one") ).to eql({ "two" => { "three" => "four" } })
expect(vivid).to eql({ "array" => [ 0, 1, 2 ], "nil" => nil })
end
@@ -339,7 +356,7 @@ describe Chef::Node::VividMash do
end
it "should unlink! nil" do
- expect(root).to receive(:reset_cache).at_least(:once).with("nil")
+ expect(root).to receive(:reset_cache).at_least(:once).with(no_args)
expect(vivid.unlink!("nil")).to eql(nil)
expect(vivid).to eql({ "one" => { "two" => { "three" => "four" } }, "array" => [ 0, 1, 2 ] })
end
diff --git a/spec/unit/node_map_spec.rb b/spec/unit/node_map_spec.rb
index 822f689eab..67bb741ec5 100644
--- a/spec/unit/node_map_spec.rb
+++ b/spec/unit/node_map_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Lamont Granquist (<lamont@chef.io>)
-# Copyright:: Copyright 2014-2017, Chef Software Inc.
+# Copyright:: Copyright 2014-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -101,6 +101,40 @@ describe Chef::NodeMap do
end
end
+ describe "platform version checks" do
+ before do
+ node_map.set(:thing, :foo, platform_family: "rhel", platform_version: ">= 7")
+ end
+
+ it "handles non-x.y.z platform versions without throwing an exception" do
+ allow(node).to receive(:[]).with(:platform_family).and_return("rhel")
+ allow(node).to receive(:[]).with(:platform_version).and_return("7.19.2.2F")
+ expect(node_map.get(node, :thing)).to eql(:foo)
+ end
+
+ it "handles non-x.y.z platform versions without throwing an exception when the match fails" do
+ allow(node).to receive(:[]).with(:platform_family).and_return("rhel")
+ allow(node).to receive(:[]).with(:platform_version).and_return("4.19.2.2F")
+ expect(node_map.get(node, :thing)).to eql(nil)
+ end
+ end
+
+ describe "ordering classes" do
+ class Foo; end
+ class Bar; end
+ it "last writer wins when its reverse alphabetic order" do
+ node_map.set(:thing, Foo)
+ node_map.set(:thing, Bar)
+ expect(node_map.get(node, :thing)).to eql(Bar)
+ end
+
+ it "last writer wins when its alphabetic order" do
+ node_map.set(:thing, Bar)
+ node_map.set(:thing, Foo)
+ expect(node_map.get(node, :thing)).to eql(Foo)
+ end
+ end
+
describe "with a block doing platform_version checks" do
before do
node_map.set(:thing, :foo, platform_family: "rhel") do |node|
diff --git a/spec/unit/node_spec.rb b/spec/unit/node_spec.rb
index 7dc972b5a0..2019f1ac42 100644
--- a/spec/unit/node_spec.rb
+++ b/spec/unit/node_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Adam Jacob (<adam@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -303,20 +303,6 @@ describe Chef::Node do
expect(node["tags"]).to eq(%w{one two three four})
end
- it "set is a deprecated alias for normal" do
- Chef::Config[:treat_deprecation_warnings_as_errors] = false
- expect(Chef).to receive(:deprecated).with(:attributes, /set is deprecated/)
- node.set[:snoopy][:is_a_puppy] = 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(:deprecated).with(:attributes, /set_unless is deprecated/)
- node.set_unless[:snoopy][:is_a_puppy] = 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
diff --git a/spec/unit/property/validation_spec.rb b/spec/unit/property/validation_spec.rb
index 13afcdfbc2..882ea3353b 100644
--- a/spec/unit/property/validation_spec.rb
+++ b/spec/unit/property/validation_spec.rb
@@ -699,4 +699,13 @@ describe "Chef::Resource.property validation" do
end
end
end
+
+ context "custom validation messages" do
+ with_property ":x, String, validation_message: 'Must be a string, fool'" do
+ it "raise with the correct error message" do
+ expect { resource.x 1 }.to raise_error Chef::Exceptions::ValidationFailed,
+ "Must be a string, fool"
+ end
+ end
+ end
end
diff --git a/spec/unit/property_spec.rb b/spec/unit/property_spec.rb
index b8cf7f5d1b..996585ab98 100644
--- a/spec/unit/property_spec.rb
+++ b/spec/unit/property_spec.rb
@@ -93,7 +93,7 @@ describe "Chef::Resource.property" do
expect(resource.bare_property).to eq 20
end
it "can be set with =" do
- expect(resource.bare_property 10).to eq 10
+ expect(resource.bare_property = 10).to eq 10
expect(resource.bare_property).to eq 10
end
it "can be set to nil with =" do
@@ -1037,20 +1037,20 @@ describe "Chef::Resource.property" do
context "default ordering deprecation warnings" do
it "emits an error for property :x, default: 10, #{name}: true" do
- expect { resource_class.property :x, :default => 10, name.to_sym => true }.to raise_error Chef::Exceptions::ArgumentError,
- /Cannot specify both default and name_property\/name_attribute together on property x of resource chef_resource_property_spec_(\d+)/
+ expect { resource_class.property :x, :default => 10, name.to_sym => true }.to raise_error ArgumentError,
+ /A property cannot be both a name_property\/name_attribute and have a default value. Use one or the other on property x of resource chef_resource_property_spec_(\d+)/
end
it "emits an error for property :x, default: nil, #{name}: true" do
- expect { resource_class.property :x, :default => nil, name.to_sym => true }.to raise_error Chef::Exceptions::ArgumentError,
- /Cannot specify both default and name_property\/name_attribute together on property x of resource chef_resource_property_spec_(\d+)/
+ expect { resource_class.property :x, :default => nil, name.to_sym => true }.to raise_error ArgumentError,
+ /A property cannot be both a name_property\/name_attribute and have a default value. Use one or the other on property x of resource chef_resource_property_spec_(\d+)/
end
it "emits an error for property :x, #{name}: true, default: 10" do
- expect { resource_class.property :x, name.to_sym => true, :default => 10 }.to raise_error Chef::Exceptions::ArgumentError,
- /Cannot specify both default and name_property\/name_attribute together on property x of resource chef_resource_property_spec_(\d+)/
+ expect { resource_class.property :x, name.to_sym => true, :default => 10 }.to raise_error ArgumentError,
+ /A property cannot be both a name_property\/name_attribute and have a default value. Use one or the other on property x of resource chef_resource_property_spec_(\d+)/
end
it "emits an error for property :x, #{name}: true, default: nil" do
- expect { resource_class.property :x, name.to_sym => true, :default => nil }.to raise_error Chef::Exceptions::ArgumentError,
- /Cannot specify both default and name_property\/name_attribute together on property x of resource chef_resource_property_spec_(\d+)/
+ expect { resource_class.property :x, name.to_sym => true, :default => nil }.to raise_error ArgumentError,
+ /A property cannot be both a name_property\/name_attribute and have a default value. Use one or the other on property x of resource chef_resource_property_spec_(\d+)/
end
end
end
@@ -1058,13 +1058,13 @@ describe "Chef::Resource.property" do
it "raises an error if both name_property and name_attribute are specified" do
expect { resource_class.property :x, :name_property => false, :name_attribute => 1 }.to raise_error ArgumentError,
- /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ /name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property x of resource chef_resource_property_spec_(\d+)./
expect { resource_class.property :x, :name_property => false, :name_attribute => nil }.to raise_error ArgumentError,
- /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ /name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property x of resource chef_resource_property_spec_(\d+)./
expect { resource_class.property :x, :name_property => false, :name_attribute => false }.to raise_error ArgumentError,
- /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ /name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property x of resource chef_resource_property_spec_(\d+)./
expect { resource_class.property :x, :name_property => true, :name_attribute => true }.to raise_error ArgumentError,
- /Cannot specify both name_property and name_attribute together on property x of resource chef_resource_property_spec_(\d+)./
+ /name_attribute and name_property are functionally identical and both cannot be specified on a property at once. Use just one on property x of resource chef_resource_property_spec_(\d+)./
end
context "property_type" do
diff --git a/spec/unit/provider/deploy/revision_spec.rb b/spec/unit/provider/deploy/revision_spec.rb
deleted file mode 100644
index 8f8280e11d..0000000000
--- a/spec/unit/provider/deploy/revision_spec.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.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::Deploy::Revision do
-
- before do
- allow(ChefConfig).to receive(:windows?) { false }
- @temp_dir = Dir.mktmpdir
- Chef::Config[:file_cache_path] = @temp_dir
- @resource = Chef::Resource::Deploy.new("/my/deploy/dir")
- @resource.revision("8a3195bf3efa246f743c5dfa83683201880f935c")
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @provider = Chef::Provider::Deploy::Revision.new(@resource, @run_context)
- @provider.load_current_resource
- @runner = double("runnah")
- allow(Chef::Runner).to receive(:new).and_return(@runner)
- @expected_release_dir = "/my/deploy/dir/releases/8a3195bf3efa246f743c5dfa83683201880f935c"
- end
-
- after do
- # Make sure we don't keep any state in our tests
- FileUtils.rm_rf @temp_dir if File.directory?( @temp_dir )
- end
-
- it "uses the resolved revision from the SCM as the release slug" do
- allow(@provider.scm_provider).to receive(:revision_slug).and_return("uglySlugly")
- expect(@provider.send(:release_slug)).to eq("uglySlugly")
- end
-
- it "deploys to a dir named after the revision" do
- expect(@provider.release_path).to eq(@expected_release_dir)
- end
-
- it "stores the release dir in the file cache in the cleanup step" do
- allow(FileUtils).to receive(:mkdir_p)
- allow(FileUtils).to receive(:cp_r)
- @provider.cleanup!
- allow(@provider).to receive(:release_slug).and_return("73219b87e977d9c7ba1aa57e9ad1d88fa91a0ec2")
- @provider.load_current_resource
- @provider.cleanup!
- second_release = "/my/deploy/dir/releases/73219b87e977d9c7ba1aa57e9ad1d88fa91a0ec2"
-
- expect(@provider.all_releases).to eq([@expected_release_dir, second_release])
- end
-
- it "removes a release from the file cache when it's used again in another release and append it to the end" do
- allow(FileUtils).to receive(:mkdir_p)
- allow(FileUtils).to receive(:cp_r)
- @provider.cleanup!
- allow(@provider).to receive(:release_slug).and_return("73219b87e977d9c7ba1aa57e9ad1d88fa91a0ec2")
- @provider.load_current_resource
- @provider.cleanup!
- second_release = "/my/deploy/dir/releases/73219b87e977d9c7ba1aa57e9ad1d88fa91a0ec2"
- expect(@provider.all_releases).to eq([@expected_release_dir, second_release])
- @provider.cleanup!
-
- allow(@provider).to receive(:release_slug).and_return("8a3195bf3efa246f743c5dfa83683201880f935c")
- @provider.load_current_resource
- @provider.cleanup!
- expect(@provider.all_releases).to eq([second_release, @expected_release_dir])
- end
-
- it "removes a release from the file cache when it's deleted by :cleanup!" do
- release_paths = %w{first second third fourth fifth}.map do |release_name|
- "/my/deploy/dir/releases/#{release_name}"
- end
- release_paths.each do |release_path|
- @provider.send(:release_created, release_path)
- end
- expect(@provider.all_releases).to eq(release_paths)
-
- allow(FileUtils).to receive(:rm_rf)
- @provider.cleanup!
-
- expected_release_paths = (%w{second third fourth fifth} << @resource.revision).map do |release_name|
- "/my/deploy/dir/releases/#{release_name}"
- end
-
- expect(@provider.all_releases).to eq(expected_release_paths)
- end
-
- it "regenerates the file cache if it's not available" do
- oldest = "/my/deploy/dir/releases/oldest"
- latest = "/my/deploy/dir/releases/latest"
- expect(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return([latest, oldest])
- expect(::File).to receive(:ctime).with(oldest).and_return(Time.now - 10)
- expect(::File).to receive(:ctime).with(latest).and_return(Time.now - 1)
- expect(@provider.all_releases).to eq([oldest, latest])
- end
-
-end
diff --git a/spec/unit/provider/deploy/timestamped_spec.rb b/spec/unit/provider/deploy/timestamped_spec.rb
deleted file mode 100644
index fdb90bf438..0000000000
--- a/spec/unit/provider/deploy/timestamped_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.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::Deploy::Timestamped do
-
- before do
- @release_time = Time.utc( 2004, 8, 15, 16, 23, 42)
- allow(Time).to receive(:now).and_return(@release_time)
- @expected_release_dir = "/my/deploy/dir/releases/20040815162342"
- @resource = Chef::Resource::Deploy.new("/my/deploy/dir")
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @timestamped_deploy = Chef::Provider::Deploy::Timestamped.new(@resource, @run_context)
- @runner = double("runnah")
- allow(Chef::Runner).to receive(:new).and_return(@runner)
- end
-
- it "gives a timestamp for release_slug" do
- expect(@timestamped_deploy.send(:release_slug)).to eq("20040815162342")
- end
-
-end
diff --git a/spec/unit/provider/deploy_spec.rb b/spec/unit/provider/deploy_spec.rb
deleted file mode 100644
index b0ede7e260..0000000000
--- a/spec/unit/provider/deploy_spec.rb
+++ /dev/null
@@ -1,641 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.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::Deploy do
-
- before do
- allow(ChefConfig).to receive(:windows?) { false }
- @release_time = Time.utc( 2004, 8, 15, 16, 23, 42)
- allow(Time).to receive(:now).and_return(@release_time)
- @expected_release_dir = "/my/deploy/dir/releases/20040815162342"
- @resource = Chef::Resource::Deploy.new("/my/deploy/dir")
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @provider = Chef::Provider::Deploy.new(@resource, @run_context)
- allow(@provider).to receive(:release_slug)
- allow(@provider).to receive(:release_path).and_return(@expected_release_dir)
- end
-
- it "loads scm resource" do
- expect(@provider.scm_provider).to receive(:load_current_resource)
- @provider.load_current_resource
- end
-
- it "supports :deploy and :rollback actions" do
- expect(@provider).to respond_to(:action_deploy)
- expect(@provider).to respond_to(:action_rollback)
- end
-
- context "when the deploy resource has a timeout attribute" do
- let(:ten_seconds) { 10 }
- before { @resource.timeout(ten_seconds) }
- it "relays the timeout to the scm resource" do
- expect(@provider.scm_provider.new_resource.timeout).to eq(ten_seconds)
- end
- end
-
- context "when the deploy resource has no timeout attribute" do
- it "should not set a timeout on the scm resource" do
- expect(@provider.scm_provider.new_resource.timeout).to be_nil
- end
- end
-
- context "when the deploy_to dir does not exist yet" do
- before do
- expect(FileUtils).to receive(:mkdir_p).with(@resource.deploy_to).ordered
- expect(FileUtils).to receive(:mkdir_p).with(@resource.shared_path).ordered
- allow(::File).to receive(:directory?).and_return(false)
- allow(@provider).to receive(:symlink)
- allow(@provider).to receive(:migrate)
- allow(@provider).to receive(:copy_cached_repo)
- end
-
- it "creates deploy_to dir" do
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).exactly(4).times
- expect(@provider).to receive(:enforce_ownership).twice
- allow(@provider).to receive(:update_cached_repo)
- @provider.deploy
- end
-
- end
-
- it "does not create deploy_to dir if it exists" do
- allow(::File).to receive(:directory?).and_return(true)
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).exactly(4).times
- expect(FileUtils).not_to receive(:mkdir_p).with(@resource.deploy_to)
- expect(FileUtils).not_to receive(:mkdir_p).with(@resource.shared_path)
- expect(@provider).to receive(:enforce_ownership).twice
- allow(@provider).to receive(:copy_cached_repo)
- allow(@provider).to receive(:update_cached_repo)
- allow(@provider).to receive(:symlink)
- allow(@provider).to receive(:migrate)
- @provider.deploy
- end
-
- it "ensures the deploy_to dir ownership after the verfication that it exists" do
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).exactly(4).times
- expect(@provider).to receive(:verify_directories_exist).ordered
- expect(@provider).to receive(:enforce_ownership).ordered
- allow(@provider).to receive(:copy_cached_repo)
- allow(@provider).to receive(:update_cached_repo)
- allow(@provider).to receive(:install_gems)
- expect(@provider).to receive(:enforce_ownership).ordered
- allow(@provider).to receive(:enforce_ownership)
- allow(@provider).to receive(:symlink)
- allow(@provider).to receive(:migrate)
- @provider.deploy
- end
-
- it "updates and copies the repo, then does a migrate, symlink, restart, restart, cleanup on deploy" do
- allow(FileUtils).to receive(:mkdir_p).with("/my/deploy/dir")
- allow(FileUtils).to receive(:mkdir_p).with("/my/deploy/dir/shared")
- expect(@provider).to receive(:enforce_ownership).twice
- expect(@provider).to receive(:update_cached_repo)
- expect(@provider).to receive(:copy_cached_repo)
- expect(@provider).to receive(:install_gems)
- expect(@provider).to receive(:callback).with(:before_migrate, nil)
- expect(@provider).to receive(:migrate)
- expect(@provider).to receive(:callback).with(:before_symlink, nil)
- expect(@provider).to receive(:symlink)
- expect(@provider).to receive(:callback).with(:before_restart, nil)
- expect(@provider).to receive(:restart)
- expect(@provider).to receive(:callback).with(:after_restart, nil)
- expect(@provider).to receive(:cleanup!)
- @provider.deploy
- end
-
- it "should not deploy if there is already a deploy at release_path, and it is the current release" do
- allow(@provider).to receive(:all_releases).and_return([@expected_release_dir])
- allow(@provider).to receive(:current_release?).with(@expected_release_dir).and_return(true)
- expect(@provider).not_to receive(:deploy)
- @provider.run_action(:deploy)
- end
-
- it "should call action_rollback if there is already a deploy of this revision at release_path, and it is not the current release" do
- allow(@provider).to receive(:all_releases).and_return([@expected_release_dir, "102021"])
- allow(@provider).to receive(:current_release?).with(@expected_release_dir).and_return(false)
- expect(@provider).to receive(:rollback_to).with(@expected_release_dir)
- expect(@provider).to receive(:current_release?)
- @provider.run_action(:deploy)
- end
-
- it "calls deploy when deploying a new release" do
- allow(@provider).to receive(:all_releases).and_return([])
- expect(@provider).to receive(:deploy)
- @provider.run_action(:deploy)
- end
-
- it "runs action svn_force_export when new_resource.svn_force_export is true" do
- @resource.svn_force_export true
- expect(@provider.scm_provider).to receive(:run_action).with(:force_export)
- @provider.update_cached_repo
- end
-
- it "Removes the old release before deploying when force deploying over it" do
- allow(@provider).to receive(:all_releases).and_return([@expected_release_dir])
- expect(FileUtils).to receive(:rm_rf).with(@expected_release_dir)
- expect(@provider).to receive(:deploy)
- @provider.run_action(:force_deploy)
- end
-
- it "deploys as normal when force deploying and there's no prior release at the same path" do
- allow(@provider).to receive(:all_releases).and_return([])
- expect(@provider).to receive(:deploy)
- @provider.run_action(:force_deploy)
- end
-
- it "dont care by default if error happens on deploy" do
- allow(@provider).to receive(:all_releases).and_return(["previous_release"])
- allow(@provider).to receive(:deploy) { raise "Unexpected error" }
- allow(@provider).to receive(:previous_release_path).and_return("previous_release")
- expect(@provider).not_to receive(:rollback)
- expect do
- @provider.run_action(:deploy)
- end.to raise_exception(RuntimeError, "Unexpected error")
- end
-
- it "rollbacks to previous release if error happens on deploy" do
- @resource.rollback_on_error true
- allow(@provider).to receive(:all_releases).and_return(["previous_release"])
- allow(@provider).to receive(:deploy) { raise "Unexpected error" }
- allow(@provider).to receive(:previous_release_path).and_return("previous_release")
- expect(@provider).to receive(:rollback)
- expect do
- @provider.run_action(:deploy)
- end.to raise_exception(RuntimeError, "Unexpected error")
- end
-
- describe "on systems without broken Dir.glob results" do
- it "sets the release path to the penultimate release when one is not specified, symlinks, and rm's the last release on rollback" do
- allow(@provider).to receive(:release_path).and_return("/my/deploy/dir/releases/3")
- all_releases = ["/my/deploy/dir/releases/1", "/my/deploy/dir/releases/2", "/my/deploy/dir/releases/3", "/my/deploy/dir/releases/4", "/my/deploy/dir/releases/5"]
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect(@provider).to receive(:symlink)
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/releases/4")
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/releases/5")
- @provider.run_action(:rollback)
- expect(@provider.release_path).to eql("/my/deploy/dir/releases/3")
- expect(@provider.shared_path).to eql("/my/deploy/dir/shared")
- end
-
- it "sets the release path to the specified release, symlinks, and rm's any newer releases on rollback" do
- allow(@provider).to receive(:release_path).and_call_original
- all_releases = ["/my/deploy/dir/releases/20040815162342", "/my/deploy/dir/releases/20040700000000",
- "/my/deploy/dir/releases/20040600000000", "/my/deploy/dir/releases/20040500000000"].sort!
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect(@provider).to receive(:symlink)
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/releases/20040815162342")
- @provider.run_action(:rollback)
- expect(@provider.release_path).to eql("/my/deploy/dir/releases/20040700000000")
- expect(@provider.shared_path).to eql("/my/deploy/dir/shared")
- end
-
- it "sets the release path to the penultimate release, symlinks, and rm's the last release on rollback" do
- allow(@provider).to receive(:release_path).and_call_original
- all_releases = [ "/my/deploy/dir/releases/20040815162342",
- "/my/deploy/dir/releases/20040700000000",
- "/my/deploy/dir/releases/20040600000000",
- "/my/deploy/dir/releases/20040500000000"]
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect(@provider).to receive(:symlink)
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/releases/20040815162342")
- @provider.run_action(:rollback)
- expect(@provider.release_path).to eql("/my/deploy/dir/releases/20040700000000")
- expect(@provider.shared_path).to eql("/my/deploy/dir/shared")
- end
-
- describe "if there are no releases to fallback to" do
-
- it "an exception is raised when there is only 1 release" do
- #@provider.unstub(:release_path) -- unstub the release path on top to feed our own release path
- all_releases = [ "/my/deploy/dir/releases/20040815162342"]
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- #@provider.should_receive(:symlink)
- #FileUtils.should_receive(:rm_rf).with("/my/deploy/dir/releases/20040815162342")
- #@provider.run_action(:rollback)
- #@provider.release_path.should eql(NIL) -- no check needed since assertions will fail
- expect do
- @provider.run_action(:rollback)
- end.to raise_exception(RuntimeError, "There is no release to rollback to!")
- end
-
- it "an exception is raised when there are no releases" do
- all_releases = []
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect do
- @provider.run_action(:rollback)
- end.to raise_exception(RuntimeError, "There is no release to rollback to!")
- end
- end
- end
-
- describe "CHEF-628: on systems with broken Dir.glob results" do
- it "sets the release path to the penultimate release, symlinks, and rm's the last release on rollback" do
- allow(@provider).to receive(:release_path).and_call_original
- all_releases = [ "/my/deploy/dir/releases/20040500000000",
- "/my/deploy/dir/releases/20040600000000",
- "/my/deploy/dir/releases/20040700000000",
- "/my/deploy/dir/releases/20040815162342" ]
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect(@provider).to receive(:symlink)
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/releases/20040815162342")
- @provider.run_action(:rollback)
- expect(@provider.release_path).to eql("/my/deploy/dir/releases/20040700000000")
- expect(@provider.shared_path).to eql("/my/deploy/dir/shared")
- end
- end
-
- it "raises a runtime error when there's no release to rollback to" do
- all_releases = []
- allow(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect { @provider.run_action(:rollback) }.to raise_error(RuntimeError)
- end
-
- it "runs the new resource collection in the runner during a callback" do
- @runner = double("Runner")
- allow(Chef::Runner).to receive(:new).and_return(@runner)
- expect(@runner).to receive(:converge)
- callback_code = Proc.new { :noop }
- @provider.callback(:whatevs, callback_code)
- end
-
- it "loads callback files from the release/ dir if the file exists" do
- foo_callback = @expected_release_dir + "/deploy/foo.rb"
- expect(::File).to receive(:exist?).with(foo_callback).once.and_return(true)
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).and_yield
- expect(@provider).to receive(:from_file).with(foo_callback)
- @provider.callback(:foo, "deploy/foo.rb")
- end
-
- it "raises a runtime error if a callback file is explicitly specified but does not exist" do
- baz_callback = "/deploy/baz.rb"
- expect(::File).to receive(:exist?).with("#{@expected_release_dir}/#{baz_callback}").and_return(false)
- @resource.before_migrate baz_callback
- @provider.define_resource_requirements
- @provider.action = :deploy
- expect { @provider.process_resource_requirements }.to raise_error(RuntimeError)
- end
-
- it "runs a default callback if the callback code is nil" do
- bar_callback = @expected_release_dir + "/deploy/bar.rb"
- expect(::File).to receive(:exist?).with(bar_callback).and_return(true)
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).and_yield
- expect(@provider).to receive(:from_file).with(bar_callback)
- @provider.callback(:bar, nil)
- end
-
- it "skips an eval callback if the file doesn't exist" do
- barbaz_callback = @expected_release_dir + "/deploy/barbaz.rb"
- expect(::File).to receive(:exist?).with(barbaz_callback).and_return(false)
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).and_yield
- expect(@provider).not_to receive(:from_file)
- @provider.callback(:barbaz, nil)
- end
-
- # CHEF-3449 #converge_by is called in #recipe_eval and must happen in sequence
- # with the other calls to #converge_by to keep the train on the tracks
- it "evaluates a callback file before the corresponding step" do
- expect(@provider).to receive(:verify_directories_exist)
- expect(@provider).to receive(:update_cached_repo)
- expect(@provider).to receive(:enforce_ownership)
- expect(@provider).to receive(:copy_cached_repo)
- expect(@provider).to receive(:install_gems)
- expect(@provider).to receive(:enforce_ownership)
- expect(@provider).to receive(:converge_by).ordered # before_migrate
- expect(@provider).to receive(:migrate).ordered
- expect(@provider).to receive(:converge_by).ordered # before_symlink
- expect(@provider).to receive(:symlink).ordered
- expect(@provider).to receive(:converge_by).ordered # before_restart
- expect(@provider).to receive(:restart).ordered
- expect(@provider).to receive(:converge_by).ordered # after_restart
- expect(@provider).to receive(:cleanup!)
- @provider.deploy
- end
-
- it "gets a SCM provider as specified by its resource" do
- expect(@provider.scm_provider).to be_an_instance_of(Chef::Provider::Git)
- expect(@provider.scm_provider.new_resource.destination).to eql("/my/deploy/dir/shared/cached-copy")
- end
-
- it "syncs the cached copy of the repo" do
- expect(@provider.scm_provider).to receive(:run_action).with(:sync)
- @provider.update_cached_repo
- end
-
- it "makes a copy of the cached repo in releases dir" do
- expect(FileUtils).to receive(:mkdir_p).with("/my/deploy/dir/releases")
- expect(FileUtils).to receive(:cp_r).with("/my/deploy/dir/shared/cached-copy/.", @expected_release_dir, :preserve => true)
- @provider.copy_cached_repo
- end
-
- it "calls the internal callback :release_created when cleaning up the releases" do
- allow(FileUtils).to receive(:mkdir_p)
- allow(FileUtils).to receive(:cp_r)
- expect(@provider).to receive(:release_created)
- @provider.cleanup!
- end
-
- it "chowns the whole release dir to user and group specified in the resource" do
- @resource.user "foo"
- @resource.group "bar"
- expect(FileUtils).to receive(:chown_R).with("foo", "bar", "/my/deploy/dir", { :force => true })
- @provider.enforce_ownership
- end
-
- it "skips the migration when resource.migrate => false but runs symlinks before migration" do
- @resource.migrate false
- expect(@provider).not_to receive :shell_out!
- expect(@provider).to receive :run_symlinks_before_migrate
- @provider.migrate
- end
-
- it "links the database.yml and runs resource.migration_command when resource.migrate #=> true" do
- @resource.migrate true
- @resource.migration_command "migration_foo"
- @resource.user "deployNinja"
- @resource.group "deployNinjas"
- @resource.environment "RAILS_ENV" => "production"
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/config/database.yml", @expected_release_dir + "/config/database.yml")
- expect(@provider).to receive(:enforce_ownership)
-
- allow(STDOUT).to receive(:tty?).and_return(true)
- allow(Chef::Log).to receive(:info?).and_return(true)
- expect(@provider).to receive(:shell_out!).with("migration_foo", :cwd => @expected_release_dir,
- :user => "deployNinja", :group => "deployNinjas",
- :log_level => :info, :live_stream => STDOUT,
- :log_tag => "deploy[/my/deploy/dir]",
- :environment => { "RAILS_ENV" => "production" })
- @provider.migrate
- end
-
- it "purges the current release's /log /tmp/pids/ and /public/system directories" do
- expect(FileUtils).to receive(:rm_rf).with(@expected_release_dir + "/log")
- expect(FileUtils).to receive(:rm_rf).with(@expected_release_dir + "/tmp/pids")
- expect(FileUtils).to receive(:rm_rf).with(@expected_release_dir + "/public/system")
- @provider.purge_tempfiles_from_current_release
- end
-
- it "symlinks temporary files and logs from the shared dir into the current release" do
- allow(FileUtils).to receive(:mkdir_p).with(@resource.shared_path + "/system")
- allow(FileUtils).to receive(:mkdir_p).with(@resource.shared_path + "/pids")
- allow(FileUtils).to receive(:mkdir_p).with(@resource.shared_path + "/log")
- expect(FileUtils).to receive(:mkdir_p).with(@expected_release_dir + "/tmp")
- expect(FileUtils).to receive(:mkdir_p).with(@expected_release_dir + "/public")
- expect(FileUtils).to receive(:mkdir_p).with(@expected_release_dir + "/config")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/system", @expected_release_dir + "/public/system")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/pids", @expected_release_dir + "/tmp/pids")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/log", @expected_release_dir + "/log")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/config/database.yml", @expected_release_dir + "/config/database.yml")
- expect(@provider).to receive(:enforce_ownership)
- @provider.link_tempfiles_to_current_release
- end
-
- it "symlinks the current release dir into production" do
- expect(FileUtils).to receive(:rm_f).with("/my/deploy/dir/current")
- expect(FileUtils).to receive(:ln_sf).with(@expected_release_dir, "/my/deploy/dir/current")
- expect(@provider).to receive(:enforce_ownership)
- @provider.link_current_release_to_production
- end
-
- context "with a customized app layout" do
-
- before do
- @resource.purge_before_symlink(%w{foo bar})
- @resource.create_dirs_before_symlink(%w{baz qux})
- @resource.symlinks "foo/bar" => "foo/bar", "baz" => "qux/baz"
- @resource.symlink_before_migrate "radiohead/in_rainbows.yml" => "awesome"
- end
-
- it "purges the purge_before_symlink directories" do
- expect(FileUtils).to receive(:rm_rf).with(@expected_release_dir + "/foo")
- expect(FileUtils).to receive(:rm_rf).with(@expected_release_dir + "/bar")
- @provider.purge_tempfiles_from_current_release
- end
-
- it "symlinks files from the shared directory to the current release directory" do
- expect(FileUtils).to receive(:mkdir_p).with(@expected_release_dir + "/baz")
- expect(FileUtils).to receive(:mkdir_p).with(@expected_release_dir + "/qux")
- allow(FileUtils).to receive(:mkdir_p).with(@resource.shared_path + "/foo/bar")
- allow(FileUtils).to receive(:mkdir_p).with(@resource.shared_path + "/baz")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/foo/bar", @expected_release_dir + "/foo/bar")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/baz", @expected_release_dir + "/qux/baz")
- expect(FileUtils).to receive(:ln_sf).with("/my/deploy/dir/shared/radiohead/in_rainbows.yml", @expected_release_dir + "/awesome")
- expect(@provider).to receive(:enforce_ownership)
- @provider.link_tempfiles_to_current_release
- end
-
- end
-
- it "does nothing for restart if restart_command is empty" do
- expect(@provider).not_to receive(:shell_out!)
- @provider.restart
- end
-
- it "runs the restart command in the current application dir when the resource has a restart_command" do
- @resource.restart_command "restartcmd"
- expect(@provider).to receive(:shell_out!).with("restartcmd", :cwd => "/my/deploy/dir/current", :log_tag => "deploy[/my/deploy/dir]", :log_level => :debug)
- @provider.restart
- end
-
- it "lists all available releases" do
- all_releases = ["/my/deploy/dir/20040815162342", "/my/deploy/dir/20040700000000",
- "/my/deploy/dir/20040600000000", "/my/deploy/dir/20040500000000"].sort!
- expect(Dir).to receive(:glob).with("/my/deploy/dir/releases/*").and_return(all_releases)
- expect(@provider.all_releases).to eql(all_releases)
- end
-
- it "removes all but the 5 newest releases" do
- all_releases = ["/my/deploy/dir/20040815162342", "/my/deploy/dir/20040700000000",
- "/my/deploy/dir/20040600000000", "/my/deploy/dir/20040500000000",
- "/my/deploy/dir/20040400000000", "/my/deploy/dir/20040300000000",
- "/my/deploy/dir/20040200000000", "/my/deploy/dir/20040100000000"].sort!
- allow(@provider).to receive(:all_releases).and_return(all_releases)
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/20040100000000")
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/20040200000000")
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/20040300000000")
- @provider.cleanup!
- end
-
- it "removes all but a certain number of releases when the resource has a keep_releases" do
- @resource.keep_releases 7
- all_releases = ["/my/deploy/dir/20040815162342", "/my/deploy/dir/20040700000000",
- "/my/deploy/dir/20040600000000", "/my/deploy/dir/20040500000000",
- "/my/deploy/dir/20040400000000", "/my/deploy/dir/20040300000000",
- "/my/deploy/dir/20040200000000", "/my/deploy/dir/20040100000000"].sort!
- allow(@provider).to receive(:all_releases).and_return(all_releases)
- expect(FileUtils).to receive(:rm_rf).with("/my/deploy/dir/20040100000000")
- @provider.cleanup!
- end
-
- it "fires a callback for :release_deleted when deleting an old release" do
- all_releases = ["/my/deploy/dir/20040815162342", "/my/deploy/dir/20040700000000",
- "/my/deploy/dir/20040600000000", "/my/deploy/dir/20040500000000",
- "/my/deploy/dir/20040400000000", "/my/deploy/dir/20040300000000"].sort!
- allow(@provider).to receive(:all_releases).and_return(all_releases)
- allow(FileUtils).to receive(:rm_rf)
- expect(@provider).to receive(:release_deleted).with("/my/deploy/dir/20040300000000")
- @provider.cleanup!
- end
-
- it "puts resource.to_hash in @configuration for backwards compat with capistano-esque deploy hooks" do
- expect(@provider.instance_variable_get(:@configuration)).to eq(@resource.to_hash)
- end
-
- it "sets @configuration[:environment] to the value of RAILS_ENV for backwards compat reasons" do
- resource = Chef::Resource::Deploy.new("/my/deploy/dir")
- resource.environment "production"
- provider = Chef::Provider::Deploy.new(resource, @run_context)
- expect(provider.instance_variable_get(:@configuration)[:environment]).to eql("production")
- end
-
- it "shouldn't give a no method error on migrate if the environment is nil" do
- allow(@provider).to receive(:enforce_ownership)
- allow(@provider).to receive(:run_symlinks_before_migrate)
- allow(@provider).to receive(:shell_out!)
- @provider.migrate
-
- end
-
- context "using inline recipes for callbacks" do
-
- it "runs an inline recipe with the provided block for :callback_name == {:recipe => &block} " do
- snitch = nil
- recipe_code = Proc.new { snitch = 42 }
- #@provider.should_receive(:instance_eval).with(&recipe_code)
- @provider.callback(:whateverz, recipe_code)
- expect(snitch).to eq(42)
- end
-
- it "loads a recipe file from the specified path and from_file evals it" do
- expect(::File).to receive(:exist?).with(@expected_release_dir + "/chefz/foobar_callback.rb").once.and_return(true)
- expect(::Dir).to receive(:chdir).with(@expected_release_dir).and_yield
- expect(@provider).to receive(:from_file).with(@expected_release_dir + "/chefz/foobar_callback.rb")
- @provider.callback(:whateverz, "chefz/foobar_callback.rb")
- end
-
- it "instance_evals a block/proc for restart command" do
- snitch = nil
- restart_cmd = Proc.new { snitch = 42 }
- @resource.restart(&restart_cmd)
- @provider.restart
- expect(snitch).to eq(42)
- end
-
- end
-
- describe "API bridge to capistrano" do
- it "defines sudo as a forwarder to execute" do
- expect(@provider).to receive(:execute).with("the moon, fool")
- @provider.sudo("the moon, fool")
- end
-
- it "defines run as a forwarder to execute, setting the user, group, cwd and environment to new_resource.user" do
- mock_execution = double("Resource::Execute")
- expect(@provider).to receive(:execute).with("iGoToHell4this").and_return(mock_execution)
- @resource.user("notCoolMan")
- @resource.group("Ggroup")
- @resource.environment("APP_ENV" => "staging")
- @resource.deploy_to("/my/app")
- expect(mock_execution).to receive(:user).with("notCoolMan")
- expect(mock_execution).to receive(:group).with("Ggroup")
- expect(mock_execution).to receive(:cwd) { |*args|
- if args.empty?
- nil
- else
- expect(args.size).to eq(1)
- expect(args.first).to eq(@provider.release_path)
- end
- }.twice
- expect(mock_execution).to receive(:environment) { |*args|
- if args.empty?
- nil
- else
- expect(args.size).to eq(1)
- expect(args.first).to eq({ "APP_ENV" => "staging" })
- end
- }.twice
- @provider.run("iGoToHell4this")
-
- end
-
- it "defines run as a forwarder to execute, setting cwd and environment but not override" do
- mock_execution = double("Resource::Execute")
- expect(@provider).to receive(:execute).with("iGoToHell4this").and_return(mock_execution)
- @resource.user("notCoolMan")
- expect(mock_execution).to receive(:user).with("notCoolMan")
- expect(mock_execution).to receive(:cwd).with(no_args()).and_return("/some/value")
- expect(mock_execution).to receive(:environment).with(no_args()).and_return({})
- @provider.run("iGoToHell4this")
- end
-
- it "converts sudo and run to exec resources in hooks" do
- runner = double("tehRunner")
- allow(Chef::Runner).to receive(:new).and_return(runner)
-
- snitch = nil
- @resource.user("tehCat")
-
- callback_code = Proc.new do
- snitch = 42
- temp_collection = resource_collection
- run("tehMice")
- snitch = temp_collection.lookup("execute[tehMice]")
- end
-
- expect(runner).to receive(:converge)
- #
- @provider.callback(:phony, callback_code)
- expect(snitch).to be_an_instance_of(Chef::Resource::Execute)
- expect(snitch.user).to eq("tehCat")
- end
- end
-
- describe "installing gems from a gems.yml" do
-
- before do
- allow(::File).to receive(:exist?).with("#{@expected_release_dir}/gems.yml").and_return(true)
- @gem_list = [{ :name => "eventmachine", :version => "0.12.9" }]
- end
-
- it "reads a gems.yml file, creating gem providers for each with action :upgrade" do
- expect(IO).to receive(:read).with("#{@expected_release_dir}/gems.yml").and_return("cookie")
- expect(YAML).to receive(:load).with("cookie").and_return(@gem_list)
-
- gems = @provider.send(:gem_packages)
-
- expect(gems.map { |g| g.action }).to eq([%i{install}])
- expect(gems.map { |g| g.name }).to eq(%w{eventmachine})
- expect(gems.map { |g| g.version }).to eq(%w{0.12.9})
- end
-
- it "takes a list of gem providers converges them" do
- allow(IO).to receive(:read)
- allow(YAML).to receive(:load).and_return(@gem_list)
- expected_gem_resources = @provider.send(:gem_packages).map { |r| [r.name, r.version] }
- gem_runner = @provider.send(:gem_resource_collection_runner)
- # no one has heard of defining == to be meaningful so I have use this monstrosity
- actual = gem_runner.run_context.resource_collection.all_resources.map { |r| [r.name, r.version] }
- expect(actual).to eq(expected_gem_resources)
- end
-
- end
-
-end
diff --git a/spec/unit/provider/erl_call_spec.rb b/spec/unit/provider/erl_call_spec.rb
deleted file mode 100644
index b5d3ae8c07..0000000000
--- a/spec/unit/provider/erl_call_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-#
-# Author:: Joe Williams (<joe@joetify.com>)
-# Copyright:: Copyright 2009-2016, Joe Williams
-# 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::ErlCall do
- before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
-
- @new_resource = Chef::Resource::ErlCall.new("test", @node)
- @new_resource.code("io:format(\"burritos\", []).")
- @new_resource.node_name("chef@localhost")
- @new_resource.name("test")
-
- @provider = Chef::Provider::ErlCall.new(@new_resource, @run_context)
-
- @status = double("Status", stdout: "{ok, woohoo}", stderr: "")
- allow(@provider).to receive(:shell_out!).and_return(@status)
- end
-
- it "should return a Chef::Provider::ErlCall object" do
- provider = Chef::Provider::ErlCall.new(@new_resource, @run_context)
- expect(provider).to be_a_kind_of(Chef::Provider::ErlCall)
- end
-
- it "should return true" do
- expect(@provider.load_current_resource).to eql(true)
- end
-
- describe "when running a distributed erl call resource" do
- before do
- @new_resource.cookie("nomnomnom")
- @new_resource.distributed(true)
- @new_resource.name_type("sname")
- end
-
- it "should write to stdin of the erl_call command" do
- expected_cmd = "erl_call -e -s -sname chef@localhost -c nomnomnom"
- expect(@provider).to receive(:shell_out!).with(expected_cmd, input: @new_resource.code).and_return(@status)
-
- @provider.action_run
- end
- end
-
- describe "when running a local erl call resource" do
- before do
- @new_resource.cookie(nil)
- @new_resource.distributed(false)
- @new_resource.name_type("name")
- end
-
- it "should write to stdin of the erl_call command" do
- expected_cmd = "erl_call -e -name chef@localhost "
- expect(@provider).to receive(:shell_out!).with(expected_cmd, input: @new_resource.code).and_return(@status)
-
- @provider.action_run
- end
- end
-
-end
diff --git a/spec/unit/provider/group/dscl_spec.rb b/spec/unit/provider/group/dscl_spec.rb
index e25b77c051..cf3f0237f5 100644
--- a/spec/unit/provider/group/dscl_spec.rb
+++ b/spec/unit/provider/group/dscl_spec.rb
@@ -117,11 +117,16 @@ describe Chef::Provider::Group::Dscl do
before do
@node = Chef::Node.new
@provider = Chef::Provider::Group::Dscl.new(@node, @new_resource)
- allow(@provider).to receive(:safe_dscl).and_return("\naj 500\n")
+ allow(@provider).to receive(:safe_dscl).and_return(<<-eos
+ someprogram somethingElse:gid = (
+ 500
+ )
+ eos
+ )
end
- it "should run safe_dscl with list /Groups gid" do
- expect(@provider).to receive(:safe_dscl).with(*"list /Groups gid".split(" "))
+ it "should run safe_dscl with search /Groups gid" do
+ expect(@provider).to receive(:safe_dscl).with(*"search /Groups PrimaryGroupID 500".split(" "))
@provider.gid_used?(500)
end
@@ -130,7 +135,11 @@ describe Chef::Provider::Group::Dscl do
end
it "should return false for an unused gid number" do
- expect(@provider.gid_used?(501)).to be_falsey
+ expect(@provider.gid_used?(0)).to be_falsey
+ expect(@provider.gid_used?(50)).to be_falsey
+ expect(@provider.gid_used?(5000)).to be_falsey
+ expect(@provider.gid_used?(1500)).to be_falsey
+ expect(@provider.gid_used?(18)).to be_falsey
end
it "should return false if not given any valid gid number" do
@@ -171,7 +180,7 @@ 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".split(" "))
+ expect(@provider).to receive(:safe_dscl).with(*"search /Groups PrimaryGroupID 50".split(" ")).and_return("")
expect(@provider).to receive(:safe_dscl).with("create", "/Groups/aj", "PrimaryGroupID", 50).and_return(true)
@provider.set_gid
end
diff --git a/spec/unit/provider/ifconfig_spec.rb b/spec/unit/provider/ifconfig_spec.rb
index da27d647ee..3732d75cc9 100644
--- a/spec/unit/provider/ifconfig_spec.rb
+++ b/spec/unit/provider/ifconfig_spec.rb
@@ -38,12 +38,19 @@ describe Chef::Provider::Ifconfig do
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
+ let(:net_tools_version) { StringIO.new <<-EOS }
+net-tools 1.60
+ifconfig 1.42 (2001-04-13)
+EOS
+
before do
- @status = double(stdout: "", exitstatus: 1)
- allow(@provider).to receive(:shell_out).and_return(@status)
+ ifconfig = double(stdout: "", exitstatus: 1)
+ allow(@provider).to receive(:shell_out).and_return(ifconfig)
+ ifconfig_version = double(stdout: "", stderr: net_tools_version, exitstatus: 4)
+ allow(@provider).to receive(:shell_out).with("ifconfig --version").and_return(ifconfig_version)
@provider.load_current_resource
end
it "should track state of ifconfig failure" do
diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb
index 20a4fd88dd..b61dc65800 100644
--- a/spec/unit/provider/mount/mount_spec.rb
+++ b/spec/unit/provider/mount/mount_spec.rb
@@ -374,6 +374,28 @@ describe Chef::Provider::Mount::Mount do
end
end
+ describe "default_mount_options" do
+ it "should return the correct default mount options for Linux" do
+ @provider.node.override[:os] = "linux"
+ expect(@provider.default_mount_options).to eq("defaults")
+ end
+
+ it "should return the correct default mount options for AIX" do
+ @provider.node.override[:os] = "aix"
+ expect(@provider.default_mount_options).to eq("rw")
+ end
+
+ it "should return the correct default mount options for Darwin" do
+ @provider.node.override[:os] = "darwin"
+ expect(@provider.default_mount_options).to eq("rw")
+ end
+
+ it "should return the correct default mount options for FreeBSD" do
+ @provider.node.override[:os] = "freebsd"
+ expect(@provider.default_mount_options).to eq("rw")
+ end
+ end
+
describe "when enabling the fs" do
it "should enable if enabled isn't true" do
@current_resource.enabled(false)
diff --git a/spec/unit/provider/package/apt_spec.rb b/spec/unit/provider/package/apt_spec.rb
index 46ae7fcadc..b461a39673 100644
--- a/spec/unit/provider/package/apt_spec.rb
+++ b/spec/unit/provider/package/apt_spec.rb
@@ -22,50 +22,48 @@ require "ostruct"
describe Chef::Provider::Package::Apt do
# XXX: sorry this is ugly and was done quickly to get 12.0.2 out, this file needs a rewrite to use
# let blocks and shared examples
- [ Chef::Resource::Package, Chef::Resource::AptPackage ].each do |resource_klass|
- describe "when the new_resource is a #{resource_klass}" do
- before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @new_resource = resource_klass.new("irssi", @run_context)
-
- @status = double("Status", :exitstatus => 0)
- @provider = Chef::Provider::Package::Apt.new(@new_resource, @run_context)
- @stdin = StringIO.new
- @stdout = <<-PKG_STATUS
+ before(:each) do
+ @node = Chef::Node.new
+ @events = Chef::EventDispatch::Dispatcher.new
+ @run_context = Chef::RunContext.new(@node, {}, @events)
+ @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
+
+ @status = double("Status", :exitstatus => 0)
+ @provider = Chef::Provider::Package::Apt.new(@new_resource, @run_context)
+ @stdin = StringIO.new
+ @stdout = <<-PKG_STATUS
irssi:
Installed: (none)
Candidate: 0.8.14-1ubuntu4
Version table:
0.8.14-1ubuntu4 0
500 http://us.archive.ubuntu.com/ubuntu/ lucid/main Packages
- PKG_STATUS
- @stderr = ""
- @shell_out = OpenStruct.new(:stdout => @stdout, :stdin => @stdin, :stderr => @stderr, :status => @status, :exitstatus => 0)
- @timeout = 900
- end
+ PKG_STATUS
+ @stderr = ""
+ @shell_out = OpenStruct.new(:stdout => @stdout, :stdin => @stdin, :stderr => @stderr, :status => @status, :exitstatus => 0)
+ @timeout = 900
+ end
+
+ describe "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(
+ "apt-cache", "policy", @new_resource.package_name,
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(@shell_out)
+ @provider.load_current_resource
+
+ current_resource = @provider.current_resource
+ expect(current_resource).to be_a(Chef::Resource::Package)
+ expect(current_resource.name).to eq("irssi")
+ expect(current_resource.package_name).to eq("irssi")
+ expect(current_resource.version).to eql([nil])
+ end
- describe "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(
- "apt-cache", "policy", @new_resource.package_name,
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(@shell_out)
- @provider.load_current_resource
-
- current_resource = @provider.current_resource
- expect(current_resource).to be_a(Chef::Resource::Package)
- expect(current_resource.name).to eq("irssi")
- expect(current_resource.package_name).to eq("irssi")
- expect(current_resource.version).to eql([nil])
- end
-
- it "should set the installed version if package has one" do
- @stdout.replace(<<-INSTALLED)
+ it "should set the installed version if package has one" do
+ @stdout.replace(<<-INSTALLED)
sudo:
Installed: 1.7.2p1-1ubuntu5.3
Candidate: 1.7.2p1-1ubuntu5.3
@@ -76,54 +74,54 @@ sudo:
100 /var/lib/dpkg/status
1.7.2p1-1ubuntu5 0
500 http://us.archive.ubuntu.com/ubuntu/ lucid/main Packages
- INSTALLED
- expect(@provider).to receive(:shell_out!).and_return(@shell_out)
- @provider.load_current_resource
- expect(@provider.current_resource.version).to eq(["1.7.2p1-1ubuntu5.3"])
- expect(@provider.candidate_version).to eql(["1.7.2p1-1ubuntu5.3"])
- end
-
- # it is the superclasses responsibility to throw most exceptions
- it "if the package does not exist in the cache sets installed + candidate version to nil" do
- @new_resource.package_name("conic-smarms")
- policy_out = <<-POLICY_STDOUT
+ INSTALLED
+ expect(@provider).to receive(:shell_out!).and_return(@shell_out)
+ @provider.load_current_resource
+ expect(@provider.current_resource.version).to eq(["1.7.2p1-1ubuntu5.3"])
+ expect(@provider.candidate_version).to eql(["1.7.2p1-1ubuntu5.3"])
+ end
+
+ # it is the superclasses responsibility to throw most exceptions
+ it "if the package does not exist in the cache sets installed + candidate version to nil" do
+ @new_resource.package_name("conic-smarms")
+ policy_out = <<-POLICY_STDOUT
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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(policy)
- showpkg_out = <<-SHOWPKG_STDOUT
+ POLICY_STDOUT
+ policy = double(:stdout => policy_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "policy", "conic-smarms",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(policy)
+ showpkg_out = <<-SHOWPKG_STDOUT
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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(showpkg)
- @provider.load_current_resource
- end
-
- # libmysqlclient-dev is a real package in newer versions of debian + ubuntu
- # list of virtual packages: http://www.debian.org/doc/packaging-manuals/virtual-package-names-list.txt
- it "should not install the virtual package there is a single provider package and it is installed" do
- @new_resource.package_name("libmysqlclient15-dev")
- virtual_package_out = <<-VPKG_STDOUT
+ SHOWPKG_STDOUT
+ showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "showpkg", "conic-smarms",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(showpkg)
+ @provider.load_current_resource
+ end
+
+ # libmysqlclient-dev is a real package in newer versions of debian + ubuntu
+ # list of virtual packages: http://www.debian.org/doc/packaging-manuals/virtual-package-names-list.txt
+ it "should not install the virtual package there is a single provider package and it is installed" do
+ @new_resource.package_name("libmysqlclient15-dev")
+ virtual_package_out = <<-VPKG_STDOUT
libmysqlclient15-dev:
Installed: (none)
Candidate: (none)
Version table:
- VPKG_STDOUT
- virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with(
- "apt-cache", "policy", "libmysqlclient15-dev",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(virtual_package)
- showpkg_out = <<-SHOWPKG_STDOUT
+ VPKG_STDOUT
+ virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "policy", "libmysqlclient15-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(virtual_package)
+ showpkg_out = <<-SHOWPKG_STDOUT
Package: libmysqlclient15-dev
Versions:
@@ -140,14 +138,14 @@ Reverse Provides:
libmysqlclient-dev 5.1.41-3ubuntu12.7
libmysqlclient-dev 5.1.41-3ubuntu12.10
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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(showpkg)
- real_package_out = <<-RPKG_STDOUT
+ SHOWPKG_STDOUT
+ showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "showpkg", "libmysqlclient15-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(showpkg)
+ real_package_out = <<-RPKG_STDOUT
libmysqlclient-dev:
Installed: 5.1.41-3ubuntu12.10
Candidate: 5.1.41-3ubuntu12.10
@@ -159,31 +157,31 @@ libmysqlclient-dev:
500 http://security.ubuntu.com/ubuntu/ lucid-security/main Packages
5.1.41-3ubuntu12 0
500 http://us.archive.ubuntu.com/ubuntu/ lucid/main Packages
- RPKG_STDOUT
- real_package = double(:stdout => real_package_out, :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with(
- "apt-cache", "policy", "libmysqlclient-dev",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(real_package)
- @provider.load_current_resource
- end
-
- it "should raise an exception if you specify a virtual package with multiple provider packages" do
- @new_resource.package_name("mp3-decoder")
- virtual_package_out = <<-VPKG_STDOUT
+ RPKG_STDOUT
+ real_package = double(:stdout => real_package_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "policy", "libmysqlclient-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(real_package)
+ @provider.load_current_resource
+ end
+
+ it "should raise an exception if you specify a virtual package with multiple provider packages" do
+ @new_resource.package_name("mp3-decoder")
+ virtual_package_out = <<-VPKG_STDOUT
mp3-decoder:
Installed: (none)
Candidate: (none)
Version table:
- VPKG_STDOUT
- virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
- expect(@provider).to receive(:shell_out!).with(
- "apt-cache", "policy", "mp3-decoder",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(virtual_package)
- showpkg_out = <<-SHOWPKG_STDOUT
+ VPKG_STDOUT
+ virtual_package = double(:stdout => virtual_package_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "policy", "mp3-decoder",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(virtual_package)
+ showpkg_out = <<-SHOWPKG_STDOUT
Package: mp3-decoder
Versions:
@@ -203,278 +201,332 @@ vlc 1.0.6-1ubuntu1
opencubicplayer 1:0.1.17-2
mpg321 0.2.10.6
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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(showpkg)
- expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Package)
- end
-
- it "should run apt-cache policy with the default_release option, if there is one on the resource" do
- @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
- @provider = Chef::Provider::Package::Apt.new(@new_resource, @run_context)
-
- @new_resource.default_release("lenny-backports")
- @new_resource.provider(nil)
- expect(@provider).to receive(:shell_out!).with(
- "apt-cache", "-o", "APT::Default-Release=lenny-backports", "policy", "irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- ).and_return(@shell_out)
- @provider.load_current_resource
- end
-
- 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,
- :env => { "DEBIAN_FRONTEND" => "noninteractive" } ,
- :timeout => @timeout
- ).and_return(@shell_out)
- expect { @provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
- end
+ SHOWPKG_STDOUT
+ showpkg = double(:stdout => showpkg_out, :exitstatus => 0)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "showpkg", "mp3-decoder",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(showpkg)
+ expect { @provider.load_current_resource }.to raise_error(Chef::Exceptions::Package)
+ end
+
+ it "should run apt-cache policy with the default_release option, if there is one on the resource" do
+ @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
+ @provider = Chef::Provider::Package::Apt.new(@new_resource, @run_context)
+
+ @new_resource.default_release("lenny-backports")
+ @new_resource.provider(nil)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-cache", "-o", "APT::Default-Release=lenny-backports", "policy", "irssi",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ ).and_return(@shell_out)
+ @provider.load_current_resource
+ end
+
+ 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,
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" } ,
+ :timeout => @timeout
+ ).and_return(@shell_out)
+ expect { @provider.run_action(:install) }.to raise_error(Chef::Exceptions::Package)
+ end
+ end
+
+ context "after loading the current resource" do
+ before do
+ @current_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
+ @provider.current_resource = @current_resource
+ allow(@provider).to receive(:package_data).and_return({
+ "irssi" => {
+ virtual: false,
+ candidate_version: "0.8.12-7",
+ installed_version: nil,
+ },
+ "libmysqlclient15-dev" => {
+ virtual: true,
+ candidate_version: nil,
+ installed_version: nil,
+ },
+ })
+ end
+
+ 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", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.install_package(["irssi"], ["0.8.12-7"])
+ end
+
+ 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", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "--force-yes", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @new_resource.options("--force-yes")
+ @provider.install_package(["irssi"], ["0.8.12-7"])
+ end
+
+ it "should run apt-get install with the package name and version and default_release if there is one and provider is explicitly defined" do
+ @new_resource = nil
+ @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
+ @new_resource.default_release("lenny-backports")
+ @new_resource.provider = nil
+ @provider.new_resource = @new_resource
+
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "-o", "APT::Default-Release=lenny-backports", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+
+ @provider.install_package(["irssi"], ["0.8.12-7"])
+ end
+
+ it "should run apt-get install with the package name and quotes options if specified" do
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "--force-yes", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confnew", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @new_resource.options('--force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew"')
+ @provider.install_package(["irssi"], ["0.8.12-7"])
+ end
+ end
+
+ describe Chef::Resource::AptPackage, "upgrade_package" do
+
+ it "should run install_package with the name and version" do
+ expect(@provider).to receive(:install_package).with(["irssi"], ["0.8.12-7"])
+ @provider.upgrade_package(["irssi"], ["0.8.12-7"])
+ end
+ end
+
+ describe Chef::Resource::AptPackage, "remove_package" do
+
+ it "should run apt-get remove with the package name" do
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "remove", "irssi",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.remove_package(["irssi"], ["0.8.12-7"])
+ end
+
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @new_resource.options("--force-yes")
+
+ @provider.remove_package(["irssi"], ["0.8.12-7"])
+ end
+ end
+
+ describe "when purging a package" do
+
+ it "should run apt-get purge with the package name" do
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "purge", "irssi",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.purge_package(["irssi"], ["0.8.12-7"])
+ end
+
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @new_resource.options("--force-yes")
+
+ @provider.purge_package(["irssi"], ["0.8.12-7"])
+ end
+ end
+
+ describe "when preseeding a package" do
+ before(:each) do
+ allow(@provider).to receive(:get_preseed_file).and_return("/tmp/irssi-0.8.12-7.seed")
+ end
+
+ it "should get the full path to the preseed response file" do
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+
+ @provider.preseed_package(file)
+ end
+
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ file = @provider.get_preseed_file("irssi", "0.8.12-7")
+ @provider.preseed_package(file)
end
- context "after loading the current resource" do
- before do
- @current_resource = resource_klass.new("irssi", @run_context)
- @provider.current_resource = @current_resource
- allow(@provider).to receive(:package_data).and_return({
- "irssi" => {
- virtual: false,
- candidate_version: "0.8.12-7",
- installed_version: nil,
- },
- "libmysqlclient15-dev" => {
- virtual: true,
- candidate_version: nil,
- installed_version: nil,
- },
- })
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.install_package(["irssi"], ["0.8.12-7"])
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @new_resource.options("--force-yes")
- @provider.install_package(["irssi"], ["0.8.12-7"])
- end
-
- it "should run apt-get install with the package name and version and default_release if there is one and provider is explicitly defined" do
- @new_resource = nil
- @new_resource = Chef::Resource::AptPackage.new("irssi", @run_context)
- @new_resource.default_release("lenny-backports")
- @new_resource.provider = nil
- @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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
-
- @provider.install_package(["irssi"], ["0.8.12-7"])
- end
-
- it "should run apt-get install with the package name and quotes options if specified" do
- expect(@provider).to receive(:shell_out!).with(
- "apt-get", "-q", "-y", "--force-yes", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confnew", "install", "irssi=0.8.12-7",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @new_resource.options('--force-yes -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew"')
- @provider.install_package(["irssi"], ["0.8.12-7"])
- end
- end
-
- describe resource_klass, "upgrade_package" do
-
- it "should run install_package with the name and version" do
- expect(@provider).to receive(:install_package).with(["irssi"], ["0.8.12-7"])
- @provider.upgrade_package(["irssi"], ["0.8.12-7"])
- end
- end
-
- describe resource_klass, "remove_package" do
-
- it "should run apt-get remove with the package name" do
- expect(@provider).to receive(:shell_out!).with(
- "apt-get", "-q", "-y", "remove", "irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.remove_package(["irssi"], ["0.8.12-7"])
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @new_resource.options("--force-yes")
-
- @provider.remove_package(["irssi"], ["0.8.12-7"])
- end
- end
-
- describe "when purging a package" do
-
- it "should run apt-get purge with the package name" do
- expect(@provider).to receive(:shell_out!).with(
- "apt-get", "-q", "-y", "purge", "irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.purge_package(["irssi"], ["0.8.12-7"])
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @new_resource.options("--force-yes")
-
- @provider.purge_package(["irssi"], ["0.8.12-7"])
- end
- end
-
- describe "when preseeding a package" do
- before(:each) do
- allow(@provider).to receive(:get_preseed_file).and_return("/tmp/irssi-0.8.12-7.seed")
- end
-
- it "should get the full path to the preseed response file" do
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
-
- @provider.preseed_package(file)
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- file = @provider.get_preseed_file("irssi", "0.8.12-7")
- @provider.preseed_package(file)
- end
-
- it "should not run debconf-set-selections if the preseed file has not changed" do
- allow(@provider).to receive(:check_all_packages_state)
- @current_resource.version "0.8.11"
- @new_resource.response_file "/tmp/file"
- allow(@provider).to receive(:get_preseed_file).and_return(false)
- expect(@provider).not_to receive(:shell_out!)
- @provider.run_action(:reconfig)
- end
- end
-
- describe "when reconfiguring a package" do
- it "should run dpkg-reconfigure package" do
- expect(@provider).to receive(:shell_out!).with(
- "dpkg-reconfigure", "irssi",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.reconfig_package("irssi", "0.8.12-7")
- end
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.lock_package("irssi", "0.8.12-7")
- end
- end
-
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.unlock_package("irssi", "0.8.12-7")
- end
- end
-
- describe "when installing a virtual package" do
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.install_package(["libmysqlclient15-dev"], ["not_a_real_version"])
- end
- end
-
- describe "when removing a virtual package" do
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.remove_package(["libmysqlclient15-dev"], ["not_a_real_version"])
- end
- end
-
- describe "when purging a virtual package" do
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.purge_package(["libmysqlclient15-dev"], ["not_a_real_version"])
- end
- end
-
- describe "when installing multiple packages" do
- 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",
- :env => { "DEBIAN_FRONTEND" => "noninteractive" },
- :timeout => @timeout
- )
- @provider.install_package(["libmysqlclient15-dev", "irssi"], ["not_a_real_version", "0.8.12-7"])
- end
- end
+ it "should not run debconf-set-selections if the preseed file has not changed" do
+ allow(@provider).to receive(:check_all_packages_state)
+ @current_resource.version "0.8.11"
+ @new_resource.response_file "/tmp/file"
+ allow(@provider).to receive(:get_preseed_file).and_return(false)
+ expect(@provider).not_to receive(:shell_out!)
+ @provider.run_action(:reconfig)
+ end
+ end
+
+ describe "when reconfiguring a package" do
+ it "should run dpkg-reconfigure package" do
+ expect(@provider).to receive(:shell_out!).with(
+ "dpkg-reconfigure", "irssi",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.reconfig_package("irssi", "0.8.12-7")
+ end
+ end
+
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.lock_package("irssi", "0.8.12-7")
+ end
+ it "should not lock if the package is already locked" do
+ allow(@provider).to receive(:shell_out_compact_timeout!).with(
+ "apt-mark", "showhold"
+ ).and_return(instance_double(
+ Mixlib::ShellOut, stdout: "irssi")
+ )
+ expect(Chef::Log).to receive(:debug).with("#{@provider.new_resource} is already locked")
+
+ @provider.new_resource.package_name = ["irssi"]
+ @provider.action_lock
+ end
+ end
+
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.unlock_package("irssi", "0.8.12-7")
+ end
+ it "should not unlock if the package is already unlocked" do
+ allow(@provider).to receive(:shell_out_compact_timeout!).with(
+ "apt-mark", "showhold"
+ ).and_return(instance_double(
+ Mixlib::ShellOut, stdout: "")
+ )
+ expect(Chef::Log).to receive(:debug).with("#{@provider.new_resource} is already unlocked")
+
+ @provider.new_resource.package_name = ["irssi"]
+ @provider.action_unlock
+ end
+ end
+
+ describe "when installing a virtual package" do
+ 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", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "libmysqlclient15-dev",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.install_package(["libmysqlclient15-dev"], ["not_a_real_version"])
+ end
+ end
+
+ describe "when removing a virtual package" do
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.remove_package(["libmysqlclient15-dev"], ["not_a_real_version"])
+ end
+ end
+
+ describe "when purging a virtual package" do
+ 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",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.purge_package(["libmysqlclient15-dev"], ["not_a_real_version"])
+ end
+ end
+
+ describe "when installing multiple packages" do
+ 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", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "libmysqlclient15-dev", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.install_package(["libmysqlclient15-dev", "irssi"], ["not_a_real_version", "0.8.12-7"])
+ end
+ end
+
+ describe "#action_install" do
+ it "should run dpkg to compare versions if an existing version is installed" do
+ allow(@provider).to receive(:get_current_versions).and_return("1.4.0")
+ allow(@new_resource).to receive(:allow_downgrade).and_return(false)
+ expect(@provider).to receive(:shell_out_compact_timeout).with(
+ "dpkg", "--compare-versions", "1.4.0", "gt", "0.8.12-7"
+ ).and_return(double(error?: false))
+ @provider.run_action(:upgrade)
+ end
+
+ it "should install the package if the installed version is older" do
+ allow(@provider).to receive(:get_current_versions).and_return("0.4.0")
+ allow(@new_resource).to receive(:allow_downgrade).and_return(false)
+ expect(@provider).to receive(:version_compare).and_return(-1)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.run_action(:upgrade)
+ end
+ it "should not compare versions if an existing version is not installed" do
+ allow(@provider).to receive(:get_current_versions).and_return(nil)
+ allow(@new_resource).to receive(:allow_downgrade).and_return(false)
+ expect(@provider).not_to receive(:version_compare)
+ expect(@provider).to receive(:shell_out!).with(
+ "apt-get", "-q", "-y", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold", "install", "irssi=0.8.12-7",
+ :env => { "DEBIAN_FRONTEND" => "noninteractive" },
+ :timeout => @timeout
+ )
+ @provider.run_action(:upgrade)
end
end
end
diff --git a/spec/unit/provider/package/chocolatey_spec.rb b/spec/unit/provider/package/chocolatey_spec.rb
index 68b121960c..afc068041d 100644
--- a/spec/unit/provider/package/chocolatey_spec.rb
+++ b/spec/unit/provider/package/chocolatey_spec.rb
@@ -59,7 +59,9 @@ 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}", { :returns => [0], timeout: timeout }).and_return(remote_list_obj)
+ package_names.each do |pkg|
+ allow(provider).to receive(:shell_out!).with("#{choco_exe} list -r #{pkg}#{args}", { :returns => [0], timeout: timeout }).and_return(remote_list_obj)
+ end
end
describe "#initialize" do
diff --git a/spec/unit/provider/package/powershell_spec.rb b/spec/unit/provider/package/powershell_spec.rb
index 4ab100f07f..4e86b0fe83 100644
--- a/spec/unit/provider/package/powershell_spec.rb
+++ b/spec/unit/provider/package/powershell_spec.rb
@@ -101,67 +101,67 @@ describe Chef::Provider::Package::Powershell do
describe "#candidate_version" do
it "should set the candidate_version to the latest version when not pinning" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force | select version | Format-Table -HideTableHeaders | Out-String).Trim()", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
new_resource.package_name(["xNetworking"])
new_resource.version(nil)
expect(provider.candidate_version).to eql(["2.12.0.0"])
end
it "should 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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.0.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available_2_0_0_0)
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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
new_resource.package_name(["xCertificate"])
expect(provider.candidate_version).to eql([nil])
end
it "should set the candidate_version correctly when there are two packages to install" do
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
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)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
new_resource.package_name(%w{xNetworking xCertificate})
new_resource.version(nil)
expect(provider.candidate_version).to eql([nil, nil])
@@ -174,8 +174,8 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
allow(provider).to receive(:powershell_out).with("$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)
@@ -186,8 +186,8 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["7-Zip 16.02 (x64)"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force | 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("(Find-Package '7-Zip 16.02 (x64)' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name '7-Zip 16.02 (x64)' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_7zip_not_installed)
allow(provider).to receive(:powershell_out).with("$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)
@@ -201,8 +201,8 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
allow(provider).to receive(:powershell_out).with("$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)
@@ -213,8 +213,8 @@ describe Chef::Provider::Package::Powershell do
it "should not install packages that are up-to-date" do
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
expect(provider).not_to receive(:install_package)
@@ -225,8 +225,8 @@ describe Chef::Provider::Package::Powershell do
it "should not install packages that are up-to-date" do
new_resource.package_name(["xNetworking"])
new_resource.version(["2.11.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force | 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("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
expect(provider).not_to receive(:install_package)
@@ -239,10 +239,10 @@ describe Chef::Provider::Package::Powershell do
# new_version.resource[0]
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version([nil, "2.11.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available_2_11_0_0)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -RequiredVersion 2.11.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$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 })
@@ -254,10 +254,10 @@ describe Chef::Provider::Package::Powershell do
it "should split up commands when given two packages, one with a version pin" do
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(["2.1.0.0", nil])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | 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("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$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 })
@@ -270,10 +270,10 @@ describe Chef::Provider::Package::Powershell do
it "should do multipackage installs when given two packages without constraints" do
new_resource.package_name(%w{xCertificate xNetworking})
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$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 })
@@ -288,8 +288,8 @@ describe Chef::Provider::Package::Powershell do
provider.load_current_resource
new_resource.package_name(["xCertificate"])
new_resource.version(["2.1.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | 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 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
expect(provider).not_to receive(:remove_package)
provider.run_action(:remove)
@@ -299,10 +299,10 @@ describe Chef::Provider::Package::Powershell do
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("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
+ allow(provider).to receive(:powershell_out).with("(Find-Package 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xNetworking' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xnetworking_not_available)
allow(provider).to receive(:powershell_out).with("$PSVersionTable.PSVersion.Major").and_return(powershell_installed_version)
provider.load_current_resource
expect(provider).not_to receive(:remove_package)
@@ -313,8 +313,8 @@ describe Chef::Provider::Package::Powershell do
it "removes a package when version is specified" do
new_resource.package_name(["xCertificate"])
new_resource.version(["2.1.0.0"])
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force | 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("(Find-Package 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -RequiredVersion 2.1.0.0 -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
allow(provider).to receive(:powershell_out).with("$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 })
@@ -325,11 +325,11 @@ describe Chef::Provider::Package::Powershell do
it "removes a package when version is not specified" do
new_resource.package_name(["xCertificate"])
new_resource.version(nil)
- allow(provider).to receive(:powershell_out).with("(Find-Package 'xCertificate' -ForceBootstrap -Force | 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("(Find-Package 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
+ allow(provider).to receive(:powershell_out).with("(Get-Package -Name 'xCertificate' -ForceBootstrap -Force).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_available)
allow(provider).to receive(:powershell_out).with("$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)
+ expect(provider).to receive(:powershell_out).with("(Uninstall-Package 'xCertificate' -Force -ForceBootstrap).Version", { :timeout => new_resource.timeout }).and_return(package_xcertificate_not_available)
provider.run_action(:remove)
expect(new_resource).to be_updated_by_last_action
end
diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb
index 856f8d460c..ac2b511ca9 100644
--- a/spec/unit/provider/package/rubygems_spec.rb
+++ b/spec/unit/provider/package/rubygems_spec.rb
@@ -383,6 +383,11 @@ describe Chef::Provider::Package::Rubygems do
provider.load_current_resource
expect(provider.target_version_already_installed?(provider.current_resource.version, new_resource.version)).to be_falsey
end
+
+ it "version_equals? should return false so that we can search for candidates" do
+ provider.load_current_resource
+ expect(provider.version_equals?(provider.current_resource.version, new_resource.version)).to be_falsey
+ end
end
describe "when new_resource version is an rspec version" do
diff --git a/spec/unit/provider/package/zypper_spec.rb b/spec/unit/provider/package/zypper_spec.rb
index b20a548c73..598fedc9fa 100644
--- a/spec/unit/provider/package/zypper_spec.rb
+++ b/spec/unit/provider/package/zypper_spec.rb
@@ -140,6 +140,14 @@ describe Chef::Provider::Package::Zypper do
provider.install_package(["emacs"], ["1.0"])
end
+ it "setting the property should allow downgrade" do
+ new_resource.allow_downgrade true
+ shell_out_expectation!(
+ "zypper", "--non-interactive", "install", "--auto-agree-with-licenses", "--oldpackage", "emacs=1.0"
+ )
+ provider.install_package(["emacs"], ["1.0"])
+ end
+
it "should add user provided options to the command" do
new_resource.options "--user-provided"
shell_out_expectation!(
diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb
index 122e58efb7..8333d5bd0d 100644
--- a/spec/unit/provider/package_spec.rb
+++ b/spec/unit/provider/package_spec.rb
@@ -27,10 +27,12 @@ describe Chef::Provider::Package do
end
let(:events) { Chef::EventDispatch::Dispatcher.new }
let(:run_context) { Chef::RunContext.new(node, {}, events) }
- let(:new_resource) { Chef::Resource::Package.new("emacs") }
- let(:current_resource) { Chef::Resource::Package.new("emacs") }
+ let(:new_resource) { Chef::Resource::Package.new("install emacs") }
+ let(:current_resource) { Chef::Resource::Package.new("install emacs") }
let(:candidate_version) { "1.0" }
let(:provider) do
+ new_resource.package_name = "emacs"
+ current_resource.package_name = "emacs"
provider = Chef::Provider::Package.new(new_resource, run_context)
provider.current_resource = current_resource
provider.candidate_version = candidate_version
@@ -57,7 +59,7 @@ describe Chef::Provider::Package do
it "should call preseed_package if a response_file is given" do
new_resource.response_file("foo")
expect(provider).to receive(:get_preseed_file).with(
- new_resource.name,
+ new_resource.package_name,
provider.candidate_version
).and_return("/var/cache/preseed-test")
@@ -74,7 +76,7 @@ describe Chef::Provider::Package do
it "should install the package at the candidate_version if it is not already installed" do
expect(provider).to receive(:install_package).with(
- new_resource.name,
+ new_resource.package_name,
provider.candidate_version
).and_return(true)
provider.run_action(:install)
@@ -84,7 +86,7 @@ describe Chef::Provider::Package do
it "should install the package at the version specified if it is not already installed" do
new_resource.version("1.0")
expect(provider).to receive(:install_package).with(
- new_resource.name,
+ new_resource.package_name,
new_resource.version
).and_return(true)
provider.run_action(:install)
@@ -95,7 +97,7 @@ describe Chef::Provider::Package do
new_resource.version("1.0")
allow(current_resource).to receive(:version).and_return("0.99")
expect(provider).to receive(:install_package).with(
- new_resource.name,
+ new_resource.package_name,
new_resource.version
).and_return(true)
provider.run_action(:install)
@@ -143,7 +145,7 @@ describe Chef::Provider::Package do
it "should upgrade the package if the current version is not the candidate version" do
expect(provider).to receive(:upgrade_package).with(
- new_resource.name,
+ new_resource.package_name,
provider.candidate_version
).and_return(true)
provider.run_action(:upgrade)
@@ -164,7 +166,7 @@ describe Chef::Provider::Package do
it "should print the word 'uninstalled' if there was no original version" do
allow(current_resource).to receive(:version).and_return(nil)
- expect(Chef::Log).to receive(:info).with("package[emacs] upgraded emacs to 1.0")
+ expect(Chef::Log).to receive(:info).with("package[install emacs] upgraded emacs to 1.0")
provider.run_action(:upgrade)
expect(new_resource).to be_updated_by_last_action
end
@@ -285,7 +287,7 @@ describe Chef::Provider::Package do
expect(provider).to receive(:get_preseed_file).and_return("/var/cache/preseed-test")
allow(provider).to receive(:preseed_package).and_return(true)
allow(provider).to receive(:reconfig_package).and_return(true)
- expect(Chef::Log).to receive(:info).with("package[emacs] reconfigured")
+ expect(Chef::Log).to receive(:info).with("package[install emacs] reconfigured")
expect(provider).to receive(:reconfig_package)
provider.run_action(:reconfig)
expect(new_resource).to be_updated
@@ -294,7 +296,7 @@ describe Chef::Provider::Package do
it "should debug log and not reconfigure the package if the package is not installed" do
allow(current_resource).to receive(:version).and_return(nil)
- expect(Chef::Log).to receive(:debug).with("package[emacs] is NOT installed - nothing to do")
+ expect(Chef::Log).to receive(:debug).with("package[install emacs] is NOT installed - nothing to do")
expect(provider).not_to receive(:reconfig_package)
provider.run_action(:reconfig)
expect(new_resource).not_to be_updated_by_last_action
@@ -303,7 +305,7 @@ describe Chef::Provider::Package do
it "should debug log and not reconfigure the package if no response_file is given" do
allow(current_resource).to receive(:version).and_return("1.0")
allow(new_resource).to receive(:response_file).and_return(nil)
- expect(Chef::Log).to receive(:debug).with("package[emacs] no response_file provided - nothing to do")
+ expect(Chef::Log).to receive(:debug).with("package[install emacs] no response_file provided - nothing to do")
expect(provider).not_to receive(:reconfig_package)
provider.run_action(:reconfig)
expect(new_resource).not_to be_updated_by_last_action
@@ -314,7 +316,7 @@ describe Chef::Provider::Package do
allow(new_resource).to receive(:response_file).and_return(true)
expect(provider).to receive(:get_preseed_file).and_return(false)
allow(provider).to receive(:preseed_package).and_return(false)
- expect(Chef::Log).to receive(:debug).with("package[emacs] preseeding has not changed - nothing to do")
+ expect(Chef::Log).to receive(:debug).with("package[install emacs] preseeding has not changed - nothing to do")
expect(provider).not_to receive(:reconfig_package)
provider.run_action(:reconfig)
expect(new_resource).not_to be_updated_by_last_action
@@ -323,24 +325,35 @@ describe Chef::Provider::Package do
describe "When locking the package" do
before(:each) do
- allow(provider).to receive(:lock_package).and_return(true)
+ allow(provider).to receive(:lock_package).with(
+ new_resource.package_name,
+ nil
+ ).and_return(true)
end
it "should lock the package if it is unlocked" do
- allow(provider).to receive(:package_locked).and_return(false)
- expect(provider).to receive(:lock_package)
+ allow(provider).to receive(:package_locked).with(
+ new_resource.package_name,
+ nil
+ ).and_return(false)
provider.run_action(:lock)
end
it "should not lock the package if it is already locked" do
- allow(provider).to receive(:package_locked).and_return(true)
+ allow(provider).to receive(:package_locked).with(
+ new_resource.package_name,
+ nil
+ ).and_return(true)
expect(provider).not_to receive(:lock_package)
provider.run_action(:lock)
expect(new_resource).not_to be_updated_by_last_action
end
it "should set the resource to updated if it locks the package" do
- allow(provider).to receive(:package_locked).and_return(false)
+ allow(provider).to receive(:package_locked).with(
+ new_resource.package_name,
+ nil
+ ).and_return(false)
provider.run_action(:lock)
expect(new_resource).to be_updated
end
@@ -352,20 +365,29 @@ describe Chef::Provider::Package do
end
it "should unlock the package if it is locked" do
- allow(provider).to receive(:package_locked).and_return(true)
+ allow(provider).to receive(:package_locked).with(
+ new_resource.package_name,
+ nil
+ ).and_return(true)
expect(provider).to receive(:unlock_package)
provider.run_action(:unlock)
end
it "should not unlock the package if it is already unlocked" do
- allow(provider).to receive(:package_locked).and_return(false)
+ allow(provider).to receive(:package_locked).with(
+ new_resource.package_name,
+ nil
+ ).and_return(false)
expect(provider).not_to receive(:unlock_package)
provider.run_action(:unlock)
expect(new_resource).not_to be_updated_by_last_action
end
it "should set the resource to updated if it unlocks the package" do
- allow(provider).to receive(:package_locked).and_return(true)
+ allow(provider).to receive(:package_locked).with(
+ new_resource.package_name,
+ nil
+ ).and_return(true)
provider.run_action(:unlock)
expect(new_resource).to be_updated
end
diff --git a/spec/unit/provider/remote_file/http_spec.rb b/spec/unit/provider/remote_file/http_spec.rb
index f58a3d3c14..ec9c0cf2e3 100644
--- a/spec/unit/provider/remote_file/http_spec.rb
+++ b/spec/unit/provider/remote_file/http_spec.rb
@@ -157,9 +157,9 @@ describe Chef::Provider::RemoteFile::HTTP do
let(:expected_http_opts) { {} }
let(:expected_http_args) { [uri, expected_http_opts] }
- let(:tempfile_path) { "/tmp/chef-mock-tempfile-abc123" }
+ let(:tempfile_path) { tempfile.path }
- let(:tempfile) { double(Tempfile, :path => tempfile_path, :close => nil) }
+ let(:tempfile) { Tempfile.open("muhtempfile") }
let(:last_response) { {} }
@@ -171,7 +171,7 @@ describe Chef::Provider::RemoteFile::HTTP do
let(:rest) do
rest = double(Chef::HTTP::Simple)
- allow(rest).to receive(:streaming_request).and_return(tempfile)
+ allow_any_instance_of(Chef::FileContentManagement::Tempfile).to receive(:tempfile).and_return(tempfile)
allow(rest).to receive(:last_response).and_return(last_response)
rest
end
@@ -189,17 +189,35 @@ describe Chef::Provider::RemoteFile::HTTP do
it "should return a nil tempfile for a 304 HTTPNotModifed" do
# Streaming request returns nil for 304 errors
- allow(rest).to receive(:streaming_request).and_return(nil)
+ expect(rest).to receive(:streaming_request).with(uri, {}, tempfile).and_return(nil)
expect(fetcher.fetch).to be_nil
end
end
- describe "and the request returns new content" do
+ context "with progress reports" do
+ let(:fetched_content_checksum) { "e2a8938cc31754f6c067b35aab1d0d4864272e9bf8504536ef3e79ebf8432305" }
+
+ before do
+ expect(cache_control_data).to receive(:save)
+ expect(Chef::Digester).to receive(:checksum_for_file).with(tempfile_path).and_return(fetched_content_checksum)
+ Chef::Config[:show_download_progress] = true
+ end
+
+ it "should yield its progress" do
+ expect(rest).to receive(:streaming_request_with_progress).with(uri, {}, tempfile).and_yield(50, 100).and_yield(70, 100).and_return(tempfile)
+ expect(event_dispatcher).to receive(:formatter?).and_return(true)
+ expect(event_dispatcher).to receive(:resource_update_progress).with(new_resource, 50, 100, 10).ordered
+ expect(event_dispatcher).to receive(:resource_update_progress).with(new_resource, 70, 100, 10).ordered
+ fetcher.fetch
+ end
+ end
+ describe "and the request returns new content" do
let(:fetched_content_checksum) { "e2a8938cc31754f6c067b35aab1d0d4864272e9bf8504536ef3e79ebf8432305" }
before do
+ expect(rest).to receive(:streaming_request).with(uri, {}, tempfile).and_return(tempfile)
expect(cache_control_data).to receive(:save)
expect(Chef::Digester).to receive(:checksum_for_file).with(tempfile_path).and_return(fetched_content_checksum)
end
@@ -212,20 +230,6 @@ describe Chef::Provider::RemoteFile::HTTP do
expect(cache_control_data.checksum).to eq(fetched_content_checksum)
end
- context "with progress reports" do
- before do
- Chef::Config[:show_download_progress] = true
- end
-
- it "should yield its progress" do
- allow(rest).to receive(:streaming_request_with_progress).and_yield(50, 100).and_yield(70, 100).and_return(tempfile)
- expect(event_dispatcher).to receive(:formatter?).and_return(true)
- expect(event_dispatcher).to receive(:resource_update_progress).with(new_resource, 50, 100, 10).ordered
- expect(event_dispatcher).to receive(:resource_update_progress).with(new_resource, 70, 100, 10).ordered
- fetcher.fetch
- end
- end
-
context "and the response does not contain an etag" do
let(:last_response) { { "etag" => nil } }
it "does not include an etag in the result" do
diff --git a/spec/unit/provider/remote_file/network_file_spec.rb b/spec/unit/provider/remote_file/network_file_spec.rb
index 621d2769a4..ecb326fc64 100644
--- a/spec/unit/provider/remote_file/network_file_spec.rb
+++ b/spec/unit/provider/remote_file/network_file_spec.rb
@@ -33,7 +33,7 @@ describe Chef::Provider::RemoteFile::NetworkFile do
let(:source_file) { double("::File", :read => nil) }
before do
- allow(fetcher).to receive(:node).and_return({ "platform_family" => "windows" })
+ allow(Chef::Platform).to receive(:windows?).and_return(true)
end
it "stages the local file to a temporary file" do
diff --git a/spec/unit/provider/route_spec.rb b/spec/unit/provider/route_spec.rb
index 5e655bda0c..ea6ddffb81 100644
--- a/spec/unit/provider/route_spec.rb
+++ b/spec/unit/provider/route_spec.rb
@@ -236,9 +236,11 @@ describe Chef::Provider::Route do
@node.automatic_attrs[:platform] = platform
route_file = StringIO.new
+ allow(File).to receive(:exist?).with("/etc/sysconfig/network").and_return(false)
expect(File).to receive(:new).with("/etc/sysconfig/network", "w").and_return(route_file)
@run_context.resource_collection << @default_resource
@default_provider.generate_config
+ expect(route_file.string).to match(/GATEWAY=10\.0\.0\.9/)
end
end
diff --git a/spec/unit/provider/service/solaris_smf_service_spec.rb b/spec/unit/provider/service/solaris_smf_service_spec.rb
index 584176b944..a5148c236a 100644
--- a/spec/unit/provider/service/solaris_smf_service_spec.rb
+++ b/spec/unit/provider/service/solaris_smf_service_spec.rb
@@ -118,6 +118,7 @@ describe Chef::Provider::Service::Solaris do
it "should create a current resource with the name of the new resource" do
expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
expect(Chef::Resource::Service).to receive(:new).and_return(@current_resource)
+ expect(@provider.maintenance).to be_falsey
@provider.load_current_resource
end
@@ -162,7 +163,7 @@ describe Chef::Provider::Service::Solaris do
end
it "should call svcadm enable -s chef" do
- expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
+ expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name)
expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", @current_resource.service_name).and_return(@success)
@provider.load_current_resource
@@ -172,7 +173,7 @@ describe Chef::Provider::Service::Solaris do
end
it "should call svcadm enable -s chef for start_service" do
- expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
+ expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name)
expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", @current_resource.service_name).and_return(@success)
@provider.load_current_resource
@@ -182,7 +183,7 @@ describe Chef::Provider::Service::Solaris do
it "should call svcadm clear chef for start_service when state maintenance" do
# we are in maint mode
- expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@maintenance_svc_status)
+ expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@maintenance_svc_status)
expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name).and_return(@success)
expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", @current_resource.service_name).and_return(@success)
@@ -205,7 +206,7 @@ describe Chef::Provider::Service::Solaris do
it "should call svcadm enable -s -r chef" do
@new_resource.options("-r")
- expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
+ expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name)
expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", "-r", @current_resource.service_name).and_return(@success)
@provider.load_current_resource
@@ -215,7 +216,7 @@ describe Chef::Provider::Service::Solaris do
it "should call svcadm enable -s -r -t chef when passed an array of options" do
@new_resource.options(["-r", "-t"])
- expect(@provider).to receive(:shell_out!).with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
+ expect(@provider).to receive(:shell_out!).twice.with("/bin/svcs", "-l", "chef", { :returns => [0, 1] }).and_return(@enabled_svc_status)
expect(@provider).not_to receive(:shell_out!).with("/usr/sbin/svcadm", "clear", @current_resource.service_name)
expect(@provider).to receive(:shell_out!).with("/usr/sbin/svcadm", "enable", "-s", "-r", "-t", @current_resource.service_name).and_return(@success)
@provider.load_current_resource
diff --git a/spec/unit/provider/service/systemd_service_spec.rb b/spec/unit/provider/service/systemd_service_spec.rb
index cbd8e88022..a9c11b7c18 100644
--- a/spec/unit/provider/service/systemd_service_spec.rb
+++ b/spec/unit/provider/service/systemd_service_spec.rb
@@ -21,16 +21,7 @@ require "spec_helper"
describe Chef::Provider::Service::Systemd do
- let(:node) do
- node = Chef::Node.new
- node.default["etc"] = Hash.new
- node.default["etc"]["passwd"] = {
- "joe" => {
- "uid" => 10000,
- },
- }
- node
- end
+ let(:node) { Chef::Node.new }
let(:events) { Chef::EventDispatch::Dispatcher.new }
@@ -56,6 +47,7 @@ describe Chef::Provider::Service::Systemd do
before(:each) do
allow(Chef::Resource::Service).to receive(:new).with(service_name).and_return(current_resource)
+ allow(Etc).to receive(:getpwuid).and_return(OpenStruct.new(uid: 10000))
end
describe "load_current_resource" do
diff --git a/spec/unit/provider/service/windows_spec.rb b/spec/unit/provider/service/windows_spec.rb
index d4c451511d..edc409fab0 100644
--- a/spec/unit/provider/service/windows_spec.rb
+++ b/spec/unit/provider/service/windows_spec.rb
@@ -23,7 +23,59 @@ require "mixlib/shellout"
describe Chef::Provider::Service::Windows, "load_current_resource" do
include_context "Win32"
- let(:new_resource) { Chef::Resource::WindowsService.new("chef") }
+ let(:chef_service_name) { "chef-client" }
+ let(:new_resource) { Chef::Resource::WindowsService.new(chef_service_name) }
+
+ # Actual response from Win32::Service.config_info('chef-client')
+ let(:chef_service_binary_path_name) do
+ 'C:\\opscode\\chef\\embedded\\bin\\ruby.exe C:\\opscode\\chef\\bin\\chef-windows-service'
+ end
+ let(:chef_service_config_info) do
+ double("Struct::ServiceConfigInfo",
+ service_type: "own process",
+ start_type: "auto start",
+ error_control: "ignore",
+ binary_path_name: chef_service_binary_path_name,
+ load_order_group: "",
+ tag_id: 0,
+ dependencies: ["Winmgmt"],
+ service_start_name: "LocalSystem",
+ display_name: "Chef Client Service"
+ )
+ end
+
+ # Actual response from Win32::Service.services
+ let(:chef_service_info) do
+ double("Struct::ServiceInfo",
+ service_name: chef_service_name,
+ display_name: "Chef Client Service",
+ service_type: "own process",
+ current_state: "running",
+ controls_accepted: [],
+ win32_exit_code: 1077,
+ service_specific_exit_code: 0,
+ check_point: 0,
+ wait_hint: 0,
+ binary_path_name: chef_service_binary_path_name,
+ start_type: "auto start",
+ error_control: "ignore",
+ load_order_group: "",
+ tag_id: 0,
+ start_name: "LocalSystem",
+ dependencies: ["Winmgmt"],
+ description: "Runs Chef Client on regular, configurable intervals.",
+ interactive: false,
+ pid: 0,
+ service_flags: 0,
+ reset_period: 0,
+ reboot_message: nil,
+ command: nil,
+ num_actions: 0,
+ actions: nil,
+ delayed_start: 1
+ )
+ end
+
let(:provider) do
prvdr = Chef::Provider::Service::Windows.new(new_resource,
Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new))
@@ -43,11 +95,35 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do
allow(Win32::Service).to receive(:status).with(new_resource.service_name).and_return(
double("StatusStruct", :current_state => "running"))
- allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return(
- double("ConfigStruct", :start_type => "auto start"))
+ allow(Win32::Service).to receive(:config_info).with(new_resource.service_name)
+ .and_return(chef_service_config_info)
+
+ # Real response from Win32::Service.services
+ allow(Win32::Service).to receive(:services).and_return([
+ # Add chef_service_info to our stubbed response so our tests that are expecting the service to exist work
+ chef_service_info,
+ double("Struct::ServiceInfo", service_name: "ACPI", display_name: "Microsoft ACPI Driver", service_type: "kernel driver", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: '\\SystemRoot\\System32\\drivers\\ACPI.sys', start_type: "boot start", error_control: "critical", load_order_group: "Core", tag_id: 2, start_name: "", dependencies: [], description: "", interactive: false, pid: 0, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 0, actions: nil, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "cdrom", display_name: "CD-ROM Driver", service_type: "kernel driver", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: '\\SystemRoot\\System32\\drivers\\cdrom.sys', start_type: "system start", error_control: "normal", load_order_group: "SCSI CDROM Class", tag_id: 3, start_name: "", dependencies: [], description: "", interactive: false, pid: 0, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 0, actions: nil, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "CryptSvc", display_name: "Cryptographic Services", service_type: "share process", current_state: "running", controls_accepted: ["shutdown", "stop", "session change"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k NetworkService', start_type: "auto start", error_control: "normal", load_order_group: "", tag_id: 0, start_name: 'NT Authority\\NetworkService', dependencies: ["RpcSs"], description: "Provides three management services: Catalog Database Service, which confirms the signatures of Windows files and allows new programs to be installed; Protected Root Service, which adds and removes Trusted Root Certification Authority certificates from this computer; and Automatic Root Certificate Update Service, which retrieves root certificates from Windows Update and enable scenarios such as SSL. If this service is stopped, these management services will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 932, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 60000 }, 2 => { action_type: "none", delay: 0 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "DcomLaunch", display_name: "DCOM Server Process Launcher", service_type: "share process", current_state: "running", controls_accepted: ["session change"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k DcomLaunch', start_type: "auto start", error_control: "normal", load_order_group: "COM Infrastructure", tag_id: 0, start_name: "LocalSystem", dependencies: [], description: "The DCOMLAUNCH service launches COM and DCOM servers in response to object activation requests. If this service is stopped or disabled, programs using COM or DCOM will not function properly. It is strongly recommended that you have the DCOMLAUNCH service running.", interactive: false, pid: 552, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 1, actions: { 1 => { action_type: "reboot", delay: 60000 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "Dfsc", display_name: "DFS Namespace Client Driver", service_type: "file system driver", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'System32\\Drivers\\dfsc.sys', start_type: "system start", error_control: "normal", load_order_group: "Network", tag_id: 0, start_name: "", dependencies: ["Mup"], description: "Client driver for access to DFS Namespaces", interactive: false, pid: 0, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 0, actions: nil, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "Dhcp", display_name: "DHCP Client", service_type: "share process", current_state: "running", controls_accepted: %w{shutdown stop}, win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted', start_type: "auto start", error_control: "normal", load_order_group: "TDI", tag_id: 0, start_name: 'NT Authority\\LocalService', dependencies: %w{NSI Tdx Afd}, description: "Registers and updates IP addresses and DNS records for this computer. If this service is stopped, this computer will not receive dynamic IP addresses and DNS updates. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 780, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 120000 }, 2 => { action_type: "restart", delay: 300000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "EventLog", display_name: "Windows Event Log", service_type: "share process", current_state: "running", controls_accepted: %w{shutdown stop}, win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\System32\\svchost.exe -k LocalServiceNetworkRestricted', start_type: "auto start", error_control: "normal", load_order_group: "Event Log", tag_id: 0, start_name: 'NT AUTHORITY\\LocalService', dependencies: [], description: "This service manages events and event logs. It supports logging events, querying events, subscribing to events, archiving event logs, and managing event metadata. It can display events in both XML and plain text format. Stopping this service may compromise security and reliability of the system.", interactive: false, pid: 780, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 60000 }, 2 => { action_type: "restart", delay: 120000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "EventSystem", display_name: "COM+ Event System", service_type: "share process", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalService', start_type: "auto start", error_control: "normal", load_order_group: "", tag_id: 0, start_name: 'NT AUTHORITY\\LocalService', dependencies: ["rpcss"], description: "Supports System Event Notification Service (SENS), which provides automatic distribution of events to subscribing Component Object Model (COM) components. If the service is stopped, SENS will close and will not be able to provide logon and logoff notifications. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 844, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 1000 }, 2 => { action_type: "restart", delay: 5000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "LanmanWorkstation", display_name: "Workstation", service_type: "share process", current_state: "running", controls_accepted: ["pause continue", "stop", "power event"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\System32\\svchost.exe -k NetworkService', start_type: "auto start", error_control: "normal", load_order_group: "NetworkProvider", tag_id: 0, start_name: 'NT AUTHORITY\\NetworkService', dependencies: %w{Bowser MRxSmb20 NSI}, description: "Creates and maintains client network connections to remote servers using the SMB protocol. If this service is stopped, these connections will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 932, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 60000 }, 2 => { action_type: "restart", delay: 120000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "lmhosts", display_name: "TCP/IP NetBIOS Helper", service_type: "share process", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted', start_type: "auto start", error_control: "normal", load_order_group: "TDI", tag_id: 0, start_name: 'NT AUTHORITY\\LocalService', dependencies: %w{NetBT Afd}, description: "Provides support for the NetBIOS over TCP/IP (NetBT) service and NetBIOS name resolution for clients on the network, therefore enabling users to share files, print, and log on to the network. If this service is stopped, these functions might be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 780, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 100 }, 2 => { action_type: "restart", delay: 100 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "MpsSvc", display_name: "Windows Firewall", service_type: "share process", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNoNetwork', start_type: "auto start", error_control: "normal", load_order_group: "NetworkProvider", tag_id: 0, start_name: 'NT Authority\\LocalService', dependencies: %w{mpsdrv bfe}, description: "Windows Firewall helps protect your computer by preventing unauthorized users from gaining access to your computer through the Internet or a network.", interactive: false, pid: 340, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 120000 }, 2 => { action_type: "restart", delay: 300000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "mrxsmb", display_name: "SMB MiniRedirector Wrapper and Engine", service_type: "file system driver", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'system32\\DRIVERS\\mrxsmb.sys', start_type: "demand start", error_control: "normal", load_order_group: "Network", tag_id: 5, start_name: "", dependencies: ["rdbss"], description: "Implements the framework for the SMB filesystem redirector", interactive: false, pid: 0, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 0, actions: nil, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "Ntfs", display_name: "Ntfs", service_type: "file system driver", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: "", start_type: "demand start", error_control: "normal", load_order_group: "Boot File System", tag_id: 0, start_name: "", dependencies: [], description: "", interactive: false, pid: 0, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 0, actions: nil, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "Tcpip", display_name: "TCP/IP Protocol Driver", service_type: "kernel driver", current_state: "running", controls_accepted: ["stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: '\\SystemRoot\\System32\\drivers\\tcpip.sys', start_type: "boot start", error_control: "normal", load_order_group: "PNP_TDI", tag_id: 3, start_name: "", dependencies: [], description: "TCP/IP Protocol Driver", interactive: false, pid: 0, service_flags: 0, reset_period: 0, reboot_message: nil, command: nil, num_actions: 0, actions: nil, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "W32Time", display_name: "Windows Time", service_type: "share process", current_state: "running", controls_accepted: ["netbind change", "param change", "shutdown", "stop", "hardware profile change", "power event"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalService', start_type: "demand start", error_control: "normal", load_order_group: "", tag_id: 0, start_name: 'NT AUTHORITY\\LocalService', dependencies: [], description: "Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 844, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 60000 }, 2 => { action_type: "restart", delay: 120000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "Winmgmt", display_name: "Windows Management Instrumentation", service_type: "share process", current_state: "running", controls_accepted: ["pause continue", "shutdown", "stop"], win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k netsvcs', start_type: "auto start", error_control: "ignore", load_order_group: "", tag_id: 0, start_name: "localSystem", dependencies: ["RPCSS"], description: "Provides a common interface and object model to access management information about operating system, devices, applications and services. If this service is stopped, most Windows-based software will not function properly. If this service is disabled, any services that explicitly depend on it will fail to start.", interactive: false, pid: 812, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 120000 }, 2 => { action_type: "restart", delay: 300000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ double("Struct::ServiceInfo", service_name: "WinRM", display_name: "Windows Remote Management (WS-Management)", service_type: "share process", current_state: "running", controls_accepted: %w{shutdown stop}, win32_exit_code: 0, service_specific_exit_code: 0, check_point: 0, wait_hint: 0, binary_path_name: 'C:\\Windows\\System32\\svchost.exe -k NetworkService', start_type: "auto start", error_control: "normal", load_order_group: "", tag_id: 0, start_name: 'NT AUTHORITY\\NetworkService', dependencies: %w{RPCSS HTTP}, description: "Windows Remote Management (WinRM) service implements the WS-Management protocol for remote management. WS-Management is a standard web services protocol used for remote software and hardware management. The WinRM service listens on the network for WS-Management requests and processes them. The WinRM Service needs to be configured with a listener using winrm.cmd command line tool or through Group Policy in order for it to listen over the network. The WinRM service provides access to WMI data and enables event collection. Event collection and subscription to events require that the service is running. WinRM messages use HTTP and HTTPS as transports. The WinRM service does not depend on IIS but is preconfigured to share a port with IIS on the same machine. The WinRM service reserves the /wsman URL prefix. To prevent conflicts with IIS, administrators should ensure that any websites hosted on IIS do not use the /wsman URL prefix.", interactive: false, pid: 932, service_flags: 0, reset_period: 86400, reboot_message: nil, command: nil, num_actions: 3, actions: { 1 => { action_type: "restart", delay: 120000 }, 2 => { action_type: "restart", delay: 300000 }, 3 => { action_type: "none", delay: 0 } }, delayed_start: 0),
+ ])
allow(Win32::Service).to receive(:exists?).and_return(true)
allow(Win32::Service).to receive(:configure).and_return(Win32::Service)
allow(Chef::ReservedNames::Win32::Security).to receive(:get_account_right).and_return([])
+ allow(Chef::ReservedNames::Win32::Security).to receive(:add_account_right).with("LocalSystem", "SeServiceLogonRight").and_return(0)
end
after(:each) do
@@ -58,28 +134,365 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do
it "sets the current resources service name to the new resources service name" do
provider.load_current_resource
- expect(provider.current_resource.service_name).to eq("chef")
+ expect(provider.current_resource.service_name).to eq(chef_service_name)
end
it "returns the current resource" do
expect(provider.load_current_resource).to equal(provider.current_resource)
end
- it "sets the current resources status" do
- provider.load_current_resource
- expect(provider.current_resource.running).to be_truthy
- end
-
it "sets the current resources start type" do
provider.load_current_resource
expect(provider.current_resource.enabled).to be_truthy
end
- it "does not set the current resources start type if it is neither AUTO START or DISABLED" do
- allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return(
- double("ConfigStruct", :start_type => "manual"))
- provider.load_current_resource
- expect(provider.current_resource.enabled).to be_nil
+ context "service does not exist" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false)
+ end
+
+ %w{running enabled startup_type error_control binary_path_name
+ load_order_group dependencies run_as_user display_name }.each do |prop|
+ it "does not set #{prop}" do
+ expect(provider.current_resource.running).to be_nil
+ end
+ end
+ end
+
+ context "service exists" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true)
+ allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return(
+ double("Struct::ServiceConfigInfo",
+ service_type: "share process",
+ start_type: "demand start",
+ error_control: "normal",
+ binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted',
+ load_order_group: "TDI",
+ tag_id: 0,
+ dependencies: %w{NSI Tdx Afd},
+ service_start_name: 'NT Authority\\LocalService',
+ display_name: "DHCP Client"
+ ))
+ end
+
+ context "startup_type is neither :automatic or :disabled" do
+ before do
+ allow(Win32::Service).to receive(:config_info).with(new_resource.service_name).and_return(
+ double("Struct::ServiceConfigInfo",
+ service_type: "share process",
+ start_type: "demand start",
+ error_control: "normal",
+ binary_path_name: 'C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted',
+ load_order_group: "TDI",
+ tag_id: 0,
+ dependencies: %w{NSI Tdx Afd},
+ service_start_name: 'NT Authority\\LocalService',
+ display_name: "DHCP Client"
+ ))
+ end
+
+ it "does not set the current resources enabled" do
+ provider.load_current_resource
+ expect(provider.current_resource.enabled).to be_nil
+ end
+ end
+
+ it "sets the current resources running to true if it's running" do
+ allow(provider).to receive(:current_state).and_return("running")
+ provider.load_current_resource
+ expect(provider.current_resource.running).to be true
+ end
+
+ it "sets the current resources running to false if it's in any other state" do
+ allow(provider).to receive(:current_state).and_return("other state")
+ provider.load_current_resource
+ expect(provider.current_resource.running).to be false
+ end
+
+ it "sets startup_type" do
+ expect(provider.current_resource.startup_type).to be_truthy
+ end
+
+ it "sets error_control" do
+ provider.load_current_resource
+ expect(provider.current_resource.error_control).to be_truthy
+ end
+
+ it "sets binary_path_name" do
+ provider.load_current_resource
+ expect(provider.current_resource.binary_path_name).to be_truthy
+ end
+
+ it "sets load_order_group" do
+ provider.load_current_resource
+ expect(provider.current_resource.load_order_group).to be_truthy
+ end
+
+ it "sets dependencies" do
+ provider.load_current_resource
+ expect(provider.current_resource.dependencies).to be_truthy
+ end
+
+ it "sets run_as_user" do
+ provider.load_current_resource
+ expect(provider.current_resource.run_as_user).to be_truthy
+ end
+
+ it "sets display_name" do
+ provider.load_current_resource
+ expect(provider.current_resource.display_name).to be_truthy
+ end
+
+ it "sets delayed start to true if delayed start is enabled" do
+ allow(chef_service_info).to receive(:delayed_start).and_return(1)
+ provider.load_current_resource
+ expect(provider.current_resource.delayed_start).to be true
+ end
+
+ it "sets delayed start to false if delayed start is disabled" do
+ allow(chef_service_info).to receive(:delayed_start).and_return(0)
+ provider.load_current_resource
+ expect(provider.current_resource.delayed_start).to be false
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "action_create" do
+ before do
+ provider.new_resource.binary_path_name = chef_service_binary_path_name
+ end
+
+ context "service exists" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true)
+ end
+
+ it "logs debug message" do
+ expect(Chef::Log).to receive(:debug).with("windows_service[#{chef_service_name}] already exists - nothing to do")
+ provider.action_create
+ end
+
+ it "does not converge" do
+ provider.action_create
+ expect(provider.resource_updated?).to be false
+ end
+
+ it "does not create service" do
+ expect(Win32::Service).to_not receive(:new)
+ provider.action_create
+ end
+
+ it "does not call converge_delayed_start" do
+ expect(provider).to_not receive(:converge_delayed_start)
+ provider.action_create
+ end
+ end
+
+ context "service does not exist" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false)
+ allow(Win32::Service).to receive(:new).with(anything).and_return(true)
+ end
+
+ it "converges resource" do
+ provider.action_create
+ expect(provider.resource_updated?).to be true
+ end
+
+ it "creates service" do
+ expect(Win32::Service).to receive(:new)
+ provider.action_create
+ end
+
+ it "creates service with correct configuration" do
+ expect(Win32::Service).to receive(:new).with(
+ service_name: chef_service_name,
+ service_type: 16,
+ start_type: 2,
+ error_control: 1,
+ binary_path_name: chef_service_binary_path_name,
+ service_start_name: "LocalSystem",
+ desired_access: 983551
+ )
+ provider.action_create
+ end
+
+ it "calls converge_delayed_start" do
+ expect(provider).to receive(:converge_delayed_start)
+ provider.action_create
+ end
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "action_delete" do
+ context "service exists" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true)
+ allow(Win32::Service).to receive(:delete).with(chef_service_name).and_return(true)
+ end
+
+ it "converges resource" do
+ provider.action_delete
+ expect(provider.resource_updated?).to be true
+ end
+
+ it "deletes service" do
+ expect(Win32::Service).to receive(:delete).with(chef_service_name)
+ provider.action_delete
+ end
+ end
+
+ context "service does not exist" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false)
+ end
+
+ it "logs debug message" do
+ expect(Chef::Log).to receive(:debug).with("windows_service[#{chef_service_name}] does not exist - nothing to do")
+ provider.action_delete
+ end
+
+ it "does not converge" do
+ provider.action_delete
+ expect(provider.resource_updated?).to be false
+ end
+
+ it "does not delete service" do
+ expect(Win32::Service).to_not receive(:delete)
+ provider.action_delete
+ end
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "action_configure" do
+ context "service exists" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(true)
+ allow(Win32::Service).to receive(:configure).with(anything).and_return(true)
+ end
+
+ it "works around #6300 if run_as_user is default" do
+ new_resource.run_as_user = new_resource.class.properties[:run_as_user].default
+ expect(provider.new_resource).to receive(:run_as_user=)
+ .with(new_resource.class.properties[:run_as_user].default)
+ provider.action_configure
+ end
+
+ # Attributes that are Strings
+ %i{binary_path_name load_order_group dependencies run_as_user
+ display_name description}.each do |attr|
+ it "configures service if #{attr} has changed" do
+ provider.current_resource.send("#{attr}=", "old value")
+ provider.new_resource.send("#{attr}=", "new value")
+
+ expect(Win32::Service).to receive(:configure)
+ provider.action_configure
+ end
+ end
+
+ # Attributes that are Integers
+ %i{service_type error_control}.each do |attr|
+ it "configures service if #{attr} has changed" do
+ provider.current_resource.send("#{attr}=", 1)
+ provider.new_resource.send("#{attr}=", 2)
+
+ expect(Win32::Service).to receive(:configure)
+ provider.action_configure
+ end
+ end
+
+ it "configures service if startup_type has changed" do
+ provider.current_resource.startup_type = :automatic
+ provider.new_resource.startup_type = :manual
+
+ expect(Win32::Service).to receive(:configure)
+ provider.action_configure
+ end
+
+ it "calls converge_delayed_start" do
+ expect(provider).to receive(:converge_delayed_start)
+ provider.action_configure
+ end
+ end
+
+ context "service does not exist" do
+ before do
+ allow(Win32::Service).to receive(:exists?).with(chef_service_name).and_return(false)
+ end
+
+ it "logs warning" do
+ expect(Chef::Log).to receive(:warn)
+ .with("windows_service[#{chef_service_name}] does not exist. Maybe you need to prepend action :create")
+ provider.action_configure
+ end
+
+ it "does not converge" do
+ provider.action_configure
+ expect(provider.resource_updated?).to be false
+ end
+
+ it "does not convigure service" do
+ expect(Win32::Service).to_not receive(:configure)
+ provider.action_configure
+ end
+
+ it "does not call converge_delayed_start" do
+ expect(provider).to_not receive(:converge_delayed_start)
+ provider.action_configure
+ end
+ end
+ end
+
+ describe Chef::Provider::Service::Windows, "converge_delayed_start" do
+ before do
+ allow(Win32::Service).to receive(:configure).and_return(true)
+ end
+
+ it "works around #6300 if delayed_start is default" do
+ new_resource.delayed_start = new_resource.class.properties[:delayed_start].default
+ expect(provider.new_resource).to receive(:delayed_start=)
+ .with(new_resource.class.properties[:delayed_start].default)
+ provider.send(:converge_delayed_start)
+ end
+
+ context "delayed start needs to be updated" do
+ before do
+ provider.current_resource.delayed_start = false
+ provider.new_resource.delayed_start = true
+ end
+
+ it "configures delayed start" do
+ expect(Win32::Service).to receive(:configure)
+ provider.send(:converge_delayed_start)
+ end
+
+ it "configures delayed start with correct params" do
+ expect(Win32::Service).to receive(:configure).with(service_name: chef_service_name, delayed_start: 1)
+ provider.send(:converge_delayed_start)
+ end
+
+ it "converges resource" do
+ provider.send(:converge_delayed_start)
+ expect(provider.resource_updated?).to be true
+ end
+ end
+
+ context "delayed start does not need to be updated" do
+ before do
+ provider.current_resource.delayed_start = false
+ provider.new_resource.delayed_start = false
+ end
+
+ it "does not configure delayed start" do
+ expect(Win32::Service).to_not receive(:configure)
+ provider.send(:converge_delayed_start)
+ end
+
+ it "does not converge" do
+ provider.send(:converge_delayed_start)
+ expect(provider.resource_updated?).to be false
+ end
+ end
end
describe Chef::Provider::Service::Windows, "start_service" do
@@ -90,7 +503,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do
end
it "calls the start command if one is specified" do
- new_resource.start_command "sc start chef"
+ new_resource.start_command "sc start #{chef_service_name}"
expect(provider).to receive(:shell_out!).with("#{new_resource.start_command}").and_return("Starting custom service")
provider.start_service
expect(new_resource.updated_by_last_action?).to be_truthy
@@ -185,7 +598,7 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do
end
it "calls the stop command if one is specified" do
- new_resource.stop_command "sc stop chef"
+ new_resource.stop_command "sc stop #{chef_service_name}"
expect(provider).to receive(:shell_out!).with("#{new_resource.stop_command}").and_return("Stopping custom service")
provider.stop_service
expect(new_resource.updated_by_last_action?).to be_truthy
@@ -369,17 +782,17 @@ describe Chef::Provider::Service::Windows, "load_current_resource" do
end
describe Chef::Provider::Service::Windows, "action_configure_startup" do
- { :automatic => "auto start", :manual => "demand start", :disabled => "disabled" }.each do |type, win32|
+ %i{automatic manual disabled}.each do |type|
it "sets the startup type to #{type} if it is something else" do
new_resource.startup_type(type)
- allow(provider).to receive(:current_start_type).and_return("fire")
+ allow(provider).to receive(:current_startup_type).and_return(:fire)
expect(provider).to receive(:set_startup_type).with(type)
provider.action_configure_startup
end
it "leaves the startup type as #{type} if it is already set" do
new_resource.startup_type(type)
- allow(provider).to receive(:current_start_type).and_return(win32)
+ allow(provider).to receive(:current_startup_type).and_return(type)
expect(provider).not_to receive(:set_startup_type).with(type)
provider.action_configure_startup
end
diff --git a/spec/unit/provider/systemd_unit_spec.rb b/spec/unit/provider/systemd_unit_spec.rb
index 6909c9d86b..15d5944992 100644
--- a/spec/unit/provider/systemd_unit_spec.rb
+++ b/spec/unit/provider/systemd_unit_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Nathan Williams (<nath.e.will@gmail.com>)
-# Copyright:: Copyright (c), Nathan Williams
+# Copyright:: Copyright 2016-2018, Nathan Williams
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,17 +19,8 @@
require "spec_helper"
describe Chef::Provider::SystemdUnit do
- let(:node) do
- Chef::Node.new.tap do |n|
- n.default["etc"] = {}
- n.default["etc"]["passwd"] = {
- "joe" => {
- "uid" => 1_000,
- },
- }
- end
- end
+ let(:node) { Chef::Node.new }
let(:events) { Chef::EventDispatch::Dispatcher.new }
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:unit_name) { "sysstat-collect\\x2d.timer" }
@@ -83,6 +74,7 @@ describe Chef::Provider::SystemdUnit do
end
before(:each) do
+ allow(Etc).to receive(:getpwuid).and_return(OpenStruct.new(uid: 1000))
allow(Chef::Resource::SystemdUnit).to receive(:new)
.with(unit_name)
.and_return(current_resource)
@@ -258,7 +250,7 @@ describe Chef::Provider::SystemdUnit do
.and_return(systemctl_path)
end
- describe "creates/deletes the unit" do
+ describe "creates/deletes/presets/reverts the unit" do
it "creates the unit file when it does not exist" do
allow(provider).to receive(:manage_unit_file)
.with(:create)
@@ -353,6 +345,22 @@ describe Chef::Provider::SystemdUnit do
expect(provider).to_not receive(:manage_unit_file)
provider.action_delete
end
+
+ it "presets the unit" do
+ new_resource.user("joe")
+ expect(provider).to receive(:shell_out_with_systems_locale!)
+ .with("#{systemctl_path} --user preset #{unit_name_escaped}", user_cmd_opts)
+ .and_return(shell_out_success)
+ provider.action_preset
+ end
+
+ it "reverts the unit" do
+ new_resource.user("joe")
+ expect(provider).to receive(:shell_out_with_systems_locale!)
+ .with("#{systemctl_path} --user revert #{unit_name_escaped}", user_cmd_opts)
+ .and_return(shell_out_success)
+ provider.action_revert
+ end
end
context "when no user is specified" do
@@ -376,11 +384,33 @@ describe Chef::Provider::SystemdUnit do
expect(provider).to_not receive(:manage_unit_file)
provider.action_delete
end
+
+ it "presets the unit" do
+ expect(provider).to receive(:shell_out_with_systems_locale!)
+ .with("#{systemctl_path} --system preset #{unit_name_escaped}", {})
+ .and_return(shell_out_success)
+ provider.action_preset
+ end
+
+ it "reverts the unit" do
+ expect(provider).to receive(:shell_out_with_systems_locale!)
+ .with("#{systemctl_path} --system revert #{unit_name_escaped}", {})
+ .and_return(shell_out_success)
+ provider.action_revert
+ end
end
end
- describe "enables/disables the unit" do
+ describe "enables/disables/reenables the unit" do
context "when a user is specified" do
+ it "reenables the unit" do
+ current_resource.user(user_name)
+ expect(provider).to receive(:shell_out_with_systems_locale!)
+ .with("#{systemctl_path} --user reenable #{unit_name_escaped}", user_cmd_opts)
+ .and_return(shell_out_success)
+ provider.action_reenable
+ end
+
it "enables the unit when it is disabled" do
current_resource.user(user_name)
current_resource.enabled(false)
@@ -429,6 +459,13 @@ describe Chef::Provider::SystemdUnit do
end
context "when no user is specified" do
+ it "reenables the unit" do
+ expect(provider).to receive(:shell_out_with_systems_locale!)
+ .with("#{systemctl_path} --system reenable #{unit_name_escaped}", {})
+ .and_return(shell_out_success)
+ provider.action_reenable
+ end
+
it "enables the unit when it is disabled" do
current_resource.enabled(false)
expect(provider).to receive(:shell_out_with_systems_locale!)
diff --git a/spec/unit/provider/user/dscl_spec.rb b/spec/unit/provider/user/dscl_spec.rb
index f59709e717..956c32664d 100644
--- a/spec/unit/provider/user/dscl_spec.rb
+++ b/spec/unit/provider/user/dscl_spec.rb
@@ -213,6 +213,32 @@ ea18e18b720e358e7fbe3cfbeaa561456f6ba008937a30"
end
end
+ describe "current_home_exists?" do
+ let(:current_resource) do
+ new_resource.dup
+ end
+
+ before do
+ provider.current_resource = current_resource
+ end
+
+ it "returns false for nil home dir" do
+ current_resource.home nil
+ expect(provider.current_home_exists?).to be_falsey
+ end
+
+ it "is false for empty string" do
+ current_resource.home ""
+ expect(provider.current_home_exists?).to be_falsey
+ end
+
+ it "is true for existing directory" do
+ current_resource.home "/Users/blah"
+ allow(::File).to receive(:exist?).with("/Users/blah").and_return(true)
+ expect(provider.current_home_exists?).to be_truthy
+ end
+ end
+
describe "when modifying the home directory" do
let(:current_resource) do
new_resource.dup
diff --git a/spec/unit/provider/windows_task_spec.rb b/spec/unit/provider/windows_task_spec.rb
index ec66cf2551..a71ce92f56 100644
--- a/spec/unit/provider/windows_task_spec.rb
+++ b/spec/unit/provider/windows_task_spec.rb
@@ -40,7 +40,7 @@ describe Chef::Provider::WindowsTask do
:LastRunTime => "3/30/2017 2:27:00 PM",
:LastResult => "1",
:Author => "Administrator",
- :TaskToRun => "chef-client",
+ :TaskToRun => "chef-client -L C:\\tmp\\",
:StartIn => "N/A",
:Comment => "N/A",
:ScheduledTaskState => "Enabled",
@@ -91,7 +91,7 @@ describe Chef::Provider::WindowsTask do
allow(provider).to receive(:load_task_hash).and_return(task_hash)
current_resource = provider.load_current_resource
expect(current_resource.exists).to be(true)
- expect(current_resource.command).to eq("chef-client")
+ expect(current_resource.command).to eq("chef-client -L C:\\tmp\\")
expect(current_resource.user).to eq("SYSTEM")
expect(current_resource.run_level).to eq(:highest)
expect(current_resource.frequency).to eq(:minute)
@@ -110,6 +110,49 @@ describe Chef::Provider::WindowsTask do
expect(new_resource).not_to be_updated_by_last_action
end
+ it "sets the start_time in 24hr format while updating an existing task" do
+ # task_hash has start_time = "1:12:00 PM"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ allow(provider).to receive(:convert_system_date_to_mm_dd_yyyy).and_return("03/30/2017")
+ allow(provider).to receive(:run_schtasks)
+ provider.run_action(:create)
+ # start_time gets set in 24hr format for new_resource
+ expect(new_resource.start_time).to eq("13:12")
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ it "sets the start_day in mm/dd/yyyy format while updating an existing task" do
+ # start_day in yyyy-MM-dd format
+ task_hash[:StartDate] = "2017-03-30"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ current_resource = provider.load_current_resource
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ allow(provider).to receive(:convert_system_date_format_to_ruby_date_format).and_return("%Y-%m-%d")
+ allow(provider).to receive(:run_schtasks)
+ provider.run_action(:create)
+ # start_day gets set in mm/dd/yyyy format for new_resource
+ expect(new_resource.start_day).to eq("03/30/2017")
+ expect(new_resource).to be_updated_by_last_action
+ end
+
+ context "when start_day and start_time are N/A for frequency :on_logon" do
+ it "doesn't update the start_day and start_time of new_resource" do
+ task_hash[:on_logon] = true
+ task_hash[:StartDate] = "N/A"
+ task_hash[:StartTime] = "N/A"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ current_resource = provider.load_current_resource
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ allow(provider).to receive(:run_schtasks)
+ expect(provider).not_to receive(:convert_system_date_to_mm_dd_yyyy)
+ expect(DateTime).not_to receive(:parse)
+ expect(new_resource.start_day).to eq(nil)
+ expect(new_resource.start_time).to eq(nil)
+ end
+ end
+
context "when task is not existing" do
before do
allow(provider).to receive(:load_task_hash)
@@ -143,6 +186,17 @@ describe Chef::Provider::WindowsTask do
provider.run_action(:create)
expect(new_resource).to be_updated_by_last_action
end
+
+ it "updates the task XML if frequency is set as `:none`" do
+ new_resource.frequency :none
+ new_resource.random_delay ""
+ allow(provider).to receive(:task_need_update?).and_return(true)
+ allow(provider).to receive(:basic_validation).and_return(true)
+ allow(provider).to receive(:run_schtasks).and_return("CREATE", { "F" => "", "SC" => :once, "ST" => "00:00", "SD" => "12/12/2012", "TR" => nil, "RU" => "SYSTEM" })
+ expect(provider).to receive(:update_task_xml)
+ provider.run_action(:create)
+ expect(new_resource).to be_updated_by_last_action
+ end
end
end
@@ -274,7 +328,7 @@ describe Chef::Provider::WindowsTask do
before do
@task_action = "CREATE"
@options = { "F" => "", "SC" => :minute, "MO" => 15, "TR" => "chef-client", "RU" => "SYSTEM", "RL" => "HIGHEST" }
- @cmd = "schtasks /CREATE /TN \"sample_task\" /F /SC \"minute\" /MO \"15\" /TR \"chef-client\" /RU \"SYSTEM\" /RL \"HIGHEST\" "
+ @cmd = "schtasks /CREATE /TN \"sample_task\" /F /SC \"minute\" /MO \"15\" /RU \"SYSTEM\" /RL \"HIGHEST\" /TR \"chef-client \" "
end
it "forms the command properly from the given options" do
@@ -325,13 +379,13 @@ describe Chef::Provider::WindowsTask do
allow(provider).to receive(:get_system_short_date_format).and_return("MM/dd/yyyy")
provider.load_current_resource
- new_resource.command "chef-client"
+ new_resource.command "chef-client -L C:\\tmp\\"
new_resource.run_level :highest
new_resource.frequency :minute
new_resource.frequency_modifier 15
new_resource.user "SYSTEM"
new_resource.execution_time_limit "PT72H"
- new_resource.start_day "30-Mar-2017"
+ new_resource.start_day "03/30/2017"
new_resource.start_time "13:12"
end
@@ -368,6 +422,13 @@ describe Chef::Provider::WindowsTask do
expect(provider.send(:task_need_update?)).to be(true)
end
end
+
+ context "when command updated" do
+ it "return true" do
+ new_resource.command "chef-client"
+ expect(provider.send(:task_need_update?)).to be(true)
+ end
+ end
end
end
@@ -383,7 +444,7 @@ describe Chef::Provider::WindowsTask do
new_resource.frequency_modifier 15
new_resource.user "SYSTEM"
new_resource.execution_time_limit "PT72H"
- new_resource.start_day "30-Mar-2017"
+ new_resource.start_day "03/30/2017"
new_resource.start_time "13:12"
end
context "when start_day not changed" do
@@ -429,9 +490,9 @@ describe Chef::Provider::WindowsTask do
end
describe "#convert_user_date_to_system_date" do
- it "when current resource start date is '30-May-2017' then returns '05/30/2017'" do
- allow(provider).to receive(:get_system_short_date_format).and_return("MM/dd/yyyy")
- expect(provider.send(:convert_user_date_to_system_date, "30-May-2017")).to eq("05/30/2017")
+ it "when current resource start date is '05/30/2017' then returns '30/05/2017'" do
+ allow(provider).to receive(:get_system_short_date_format).and_return("dd/MM/yyyy")
+ expect(provider.send(:convert_user_date_to_system_date, "05/30/2017")).to eq("30/05/2017")
end
end
@@ -507,6 +568,18 @@ describe Chef::Provider::WindowsTask do
expect(provider).to receive(:run_schtasks).twice
output = provider.send(:update_task_xml, ["random_delay"])
end
+
+ it "updates the task XML if frequency is set as `:none`" do
+ new_resource.frequency :none
+ new_resource.random_delay ""
+ shell_out_obj = double("xml", :exitstatus => 0, :stdout => task_xml)
+ allow(provider).to receive(:powershell_out).and_return(shell_out_obj)
+ expect(::File).to receive(:delete)
+ expect(::File).to receive(:join)
+ expect(::File).to receive(:open)
+ expect(provider).to receive(:run_schtasks).twice
+ output = provider.send(:update_task_xml, ["random_delay"])
+ end
end
describe "#load_task_hash" do
@@ -541,5 +614,104 @@ describe Chef::Provider::WindowsTask do
new_resource.frequency :once
expect(provider.send(:frequency_modifier_allowed)).to be(false)
end
+
+ it "returns false for frequency :none" do
+ new_resource.frequency :none
+ expect(provider.send(:frequency_modifier_allowed)).to be(false)
+ end
+ end
+
+ # In windows_task resource sec_to_dur method converts seconds to duration in format 60 == 'PT60S'
+ # random_delay_updated? method use the value return by sec_to_dur as input for comparison for new_resource.random_delay mocking the same here
+ describe "#random_delay_updated?" do
+ before do
+ new_resource.command "chef-client"
+ new_resource.run_level :highest
+ new_resource.frequency :minute
+ new_resource.frequency_modifier 15
+ new_resource.user "SYSTEM"
+ end
+
+ it "returns false if current_resource.random_delay = nil & random_delay is set to '0' seconds" do
+ task_hash[:random_delay] = nil
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.random_delay = "PT0S"
+ expect(provider.send(:random_delay_updated?)).to be(false)
+ end
+
+ it "returns false if current_resource.random_delay = 'P7D' & random_delay is set to '604800' seconds " do
+ task_hash[:random_delay] = "P7D"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.random_delay = "PT604800S"
+ expect(provider.send(:random_delay_updated?)).to be(false)
+ end
+
+ it "returns false if current_resource.random_delay = 'P7DT1S' & random_delay is set to '604801' seconds" do
+ task_hash[:random_delay] = "P7DT1S"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.random_delay = "PT604801S"
+ expect(provider.send(:random_delay_updated?)).to be(false)
+ end
+
+ it "returns true if current_resource.random_delay = 'PT1S' & random_delay is set to '3600' seconds" do
+ task_hash[:random_delay] = "PT1S"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.random_delay = "PT3600S"
+ expect(provider.send(:random_delay_updated?)).to be(true)
+ end
+
+ it "returns false if current_resource.random_delay = 'P2Y1MT2H' & random_delay is set to '65707200' seconds" do
+ task_hash[:random_delay] = "P2Y1MT2H"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.random_delay = "PT65707200S"
+ expect(provider.send(:random_delay_updated?)).to be(false)
+ end
+ end
+
+ describe "#execution_time_limit_updated?" do
+ before do
+ new_resource.command "chef-client"
+ new_resource.run_level :highest
+ new_resource.frequency :minute
+ new_resource.frequency_modifier 15
+ new_resource.user "SYSTEM"
+ end
+
+ it "returns false if current_resource.execution_time_limit = 'P7D' & execution_time_limit is set to 604800 seconds " do
+ task_hash[:execution_time_limit] = "P7D"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.execution_time_limit = "PT604800S"
+ expect(provider.send(:execution_time_limit_updated?)).to be(false)
+ end
+
+ it "returns false if current_resource.execution_time_limit = 'P7DT1S' & execution_time_limit is set to 604801 seconds" do
+ task_hash[:execution_time_limit] = "P7DT1S"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.execution_time_limit = "PT604801S"
+ expect(provider.send(:execution_time_limit_updated?)).to be(false)
+ end
+
+ it "returns true if current_resource.execution_time_limit = 'PT1S' & execution_time_limit is set to '3600' seconds" do
+ task_hash[:execution_time_limit] = "PT1S"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.execution_time_limit = "PT3600S"
+ expect(provider.send(:execution_time_limit_updated?)).to be(true)
+ end
+
+ it "returns false if current_resource.execution_time_limit = 'P2Y1MT2H' & execution_time_limit is set to '65707200' seconds" do
+ task_hash[:execution_time_limit] = "P2Y1MT2H"
+ allow(provider).to receive(:load_task_hash).and_return(task_hash)
+ provider.load_current_resource
+ new_resource.execution_time_limit = "PT65707200S"
+ expect(provider.send(:execution_time_limit_updated?)).to be(false)
+ end
end
end
diff --git a/spec/unit/provider/zypper_repository_spec.rb b/spec/unit/provider/zypper_repository_spec.rb
new file mode 100644
index 0000000000..a366a33e86
--- /dev/null
+++ b/spec/unit/provider/zypper_repository_spec.rb
@@ -0,0 +1,124 @@
+#
+# Author:: Tim Smith (<tsmith@chef.io>)
+# 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"
+
+# Output of the command:
+# => rpm -qa gpg-pubkey*
+RPM_KEYS = <<-EOF
+gpg-pubkey-307e3d54-4be01a65
+gpg-pubkey-3dbdc284-53674dd4
+EOF
+
+# Output of the command:
+# => gpg --with-fingerprint [FILE]
+GPG_FINGER = <<-EOF
+pub 2048R/3DBDC284 2011-08-19 [expires: 2024-06-14]
+ Key fingerprint = 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
+uid nginx signing key <signing-key@nginx.com>
+EOF
+
+describe Chef::Provider::ZypperRepository do
+ let(:new_resource) { Chef::Resource::ZypperRepository.new("Nginx Repository") }
+ let(:provider) do
+ node = Chef::Node.new
+ events = Chef::EventDispatch::Dispatcher.new
+ run_context = Chef::RunContext.new(node, {}, events)
+ Chef::Provider::ZypperRepository.new(new_resource, run_context)
+ end
+
+ let(:rpm_key_finger) do
+ double("shell_out_with_systems_locale", stdout: RPM_KEYS, exitstatus: 0, error?: false)
+ end
+
+ let(:gpg_finger) do
+ double("shell_out_with_systems_locale", stdout: GPG_FINGER, exitstatus: 0, error?: false)
+ end
+
+ it "responds to load_current_resource" do
+ expect(provider).to respond_to(:load_current_resource)
+ end
+
+ describe "#action_create" do
+ it "skips key import if gpgautoimportkeys is false" do
+ new_resource.gpgautoimportkeys(false)
+ expect(provider).to receive(:declare_resource)
+ expect(Chef::Log).to receive(:debug)
+ provider.run_action(:create)
+ end
+ end
+
+ describe "#escaped_repo_name" do
+ it "returns an escaped repo name" do
+ expect(provider.escaped_repo_name).to eq('Nginx\\ Repository')
+ end
+ end
+
+ describe "#cookbook_name" do
+ it "returns 'test' when the cookbook property is set" do
+ new_resource.cookbook("test")
+ expect(provider.cookbook_name).to eq("test")
+ end
+ end
+
+ describe "#key_type" do
+ it "returns :remote_file with an http URL" do
+ expect(provider.key_type("https://www.chef.io/key")).to eq(:remote_file)
+ end
+
+ it "returns :cookbook_file with a chef managed file" do
+ expect(provider).to receive(:has_cookbook_file?).and_return(true)
+ expect(provider.key_type("/foo/nginx.key")).to eq(:cookbook_file)
+ end
+
+ it "throws exception if an unknown file specified" do
+ expect(provider).to receive(:has_cookbook_file?).and_return(false)
+ expect { provider.key_type("/foo/nginx.key") }.to raise_error(Chef::Exceptions::FileNotFound)
+ end
+ end
+
+ describe "#key_installed?" do
+ before do
+ expect(provider).to receive(:shell_out).with("rpm -qa gpg-pubkey*").and_return(rpm_key_finger)
+ end
+
+ it "returns true if the key is installed" do
+ expect(provider).to receive(:key_fingerprint).and_return("3dbdc284")
+ expect(provider.key_installed?("/foo/nginx.key")).to be_truthy
+ end
+
+ it "returns false if the key is not installed" do
+ expect(provider).to receive(:key_fingerprint).and_return("BOGUS")
+ expect(provider.key_installed?("/foo/nginx.key")).to be_falsey
+ end
+ end
+
+ describe "#key_fingerprint" do
+ it "returns the key's fingerprint" do
+ expect(provider).to receive(:shell_out!).with("gpg --with-fingerprint /foo/nginx.key").and_return(gpg_finger)
+ expect(provider.key_fingerprint("/foo/nginx.key")).to eq("3dbdc284")
+ end
+ end
+
+ describe "#install_gpg_key" do
+ it "skips installing the key if a nil value for key is passed" do
+ expect(Chef::Log).to receive(:debug)
+ provider.install_gpg_key(nil)
+ end
+ end
+end
diff --git a/spec/unit/provider_resolver_spec.rb b/spec/unit/provider_resolver_spec.rb
index 1902fb5375..a331093055 100644
--- a/spec/unit/provider_resolver_spec.rb
+++ b/spec/unit/provider_resolver_spec.rb
@@ -558,10 +558,7 @@ describe Chef::ProviderResolver do
chef_gem: [ Chef::Resource::ChefGem, Chef::Provider::Package::Rubygems ],
cookbook_file: [ Chef::Resource::CookbookFile, Chef::Provider::CookbookFile ],
csh: [ Chef::Resource::Csh, Chef::Provider::Script ],
- deploy: [ Chef::Resource::Deploy, Chef::Provider::Deploy::Timestamped ],
- deploy_revision: [ Chef::Resource::DeployRevision, Chef::Provider::Deploy::Revision ],
directory: [ Chef::Resource::Directory, Chef::Provider::Directory ],
- erl_call: [ Chef::Resource::ErlCall, Chef::Provider::ErlCall ],
execute: [ Chef::Resource::Execute, Chef::Provider::Execute ],
file: [ Chef::Resource::File, Chef::Provider::File ],
gem_package: [ Chef::Resource::GemPackage, Chef::Provider::Package::Rubygems ],
@@ -585,7 +582,6 @@ describe Chef::ProviderResolver do
script: [ Chef::Resource::Script, Chef::Provider::Script ],
subversion: [ Chef::Resource::Subversion, Chef::Provider::Subversion ],
template: [ Chef::Resource::Template, Chef::Provider::Template ],
- timestamped_deploy: [ Chef::Resource::TimestampedDeploy, Chef::Provider::Deploy::Timestamped ],
aix_user: [ Chef::Resource::User::AixUser, Chef::Provider::User::Aix ],
dscl_user: [ Chef::Resource::User::DsclUser, Chef::Provider::User::Dscl ],
linux_user: [ Chef::Resource::User::LinuxUser, Chef::Provider::User::Linux ],
@@ -708,18 +704,21 @@ describe Chef::ProviderResolver do
"rhel" => {
# service: [ Chef::Resource::SystemdService, Chef::Provider::Service::Systemd ],
- package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
+ package: [ Chef::Resource::DnfPackage, Chef::Provider::Package::Dnf ],
ifconfig: [ Chef::Resource::Ifconfig, Chef::Provider::Ifconfig::Redhat ],
%w{amazon xcp xenserver ibm_powerkvm cloudlinux parallels} => {
"3.1.4" => {
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
},
},
%w{redhat centos scientific oracle} => {
"7.0" => {
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
},
"6.0" => {
+ package: [ Chef::Resource::YumPackage, Chef::Provider::Package::Yum ],
# service: [ Chef::Resource::RedhatService, Chef::Provider::Service::Redhat ],
},
},
diff --git a/spec/unit/provider_spec.rb b/spec/unit/provider_spec.rb
index 6eb2bb9303..2565df8960 100644
--- a/spec/unit/provider_spec.rb
+++ b/spec/unit/provider_spec.rb
@@ -197,7 +197,7 @@ describe Chef::Provider do
context "when using use_inline_resources" do
it "should log a deprecation warning" do
- pending Chef::VERSION.start_with?("13.6")
+ pending Chef::VERSION.start_with?("14.1")
expect(Chef).to receive(:deprecated).with(:use_inline_resources, kind_of(String))
Class.new(described_class) { use_inline_resources }
end
diff --git a/spec/unit/recipe_spec.rb b/spec/unit/recipe_spec.rb
index 7a538b721b..93d03756a7 100644
--- a/spec/unit/recipe_spec.rb
+++ b/spec/unit/recipe_spec.rb
@@ -3,7 +3,7 @@
# Author:: Christopher Walters (<cw@chef.io>)
# Author:: Tim Hinderliter (<tim@chef.io>)
# Author:: Seth Chisamore (<schisamo@chef.io>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
+# Copyright:: Copyright 2008-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -141,16 +141,16 @@ describe Chef::Recipe do
Object.send(:remove_const, :TottenhamHotspur)
end
- it "selects the first one alphabetically" do
+ it "selects the last-writer wins" do
Sounders.provides :football, platform: "nbc_sports"
TottenhamHotspur.provides :football, platform: "nbc_sports"
res1 = recipe.football "club world cup"
expect(res1.name).to eql("club world cup")
- expect(res1).to be_a_kind_of(Sounders)
+ expect(res1).to be_a_kind_of(TottenhamHotspur)
end
- it "selects the first one alphabetically even if the declaration order is reversed" do
+ it "selects the last-writer wins even if the declaration order is reversed" do
TottenhamHotspur.provides :football2, platform: "nbc_sports"
Sounders.provides :football2, platform: "nbc_sports"
diff --git a/spec/unit/resource/apt_package_spec.rb b/spec/unit/resource/apt_package_spec.rb
index 78eccfb444..3b399059a6 100644
--- a/spec/unit/resource/apt_package_spec.rb
+++ b/spec/unit/resource/apt_package_spec.rb
@@ -31,8 +31,12 @@ describe Chef::Resource::AptPackage, "initialize" do
let(:resource) { Chef::Resource::AptPackage.new("foo") }
- it "should support default_release" do
+ it "supports default_release" do
resource.default_release("lenny-backports")
expect(resource.default_release).to eql("lenny-backports")
end
+
+ it "should preserve configuration files by default" do
+ expect(resource.overwrite_config_files).to eql(false)
+ end
end
diff --git a/spec/unit/resource/apt_preference_spec.rb b/spec/unit/resource/apt_preference_spec.rb
index 66bb6e64bb..1d3be99f44 100644
--- a/spec/unit/resource/apt_preference_spec.rb
+++ b/spec/unit/resource/apt_preference_spec.rb
@@ -24,11 +24,6 @@ describe Chef::Resource::AptPreference do
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:resource) { Chef::Resource::AptPreference.new("libmysqlclient16", run_context) }
- it "creates a new Chef::Resource::AptPreference" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::AptPreference)
- end
-
it "resolves to a Noop class when on non-linux OS" do
node.automatic[:os] = "windows"
node.automatic[:platform_family] = "windows"
diff --git a/spec/unit/resource/apt_repository_spec.rb b/spec/unit/resource/apt_repository_spec.rb
index 812fa0c843..fecf3be582 100644
--- a/spec/unit/resource/apt_repository_spec.rb
+++ b/spec/unit/resource/apt_repository_spec.rb
@@ -24,20 +24,10 @@ describe Chef::Resource::AptRepository do
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:resource) { Chef::Resource::AptRepository.new("multiverse", run_context) }
- it "creates a new Chef::Resource::AptRepository" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::AptRepository)
- end
-
it "uses keyserver.ubuntu.com as the keyserver" do
expect(resource.keyserver).to eql("keyserver.ubuntu.com")
end
- it "default distribution is nillable" do
- expect(resource.distribution(nil)).to eql(nil)
- expect(resource.distribution).to eql(nil)
- end
-
it "resolves to a Noop class when on non-linux OS" do
node.automatic[:os] = "windows"
node.automatic[:platform_family] = "windows"
diff --git a/spec/unit/resource/apt_update_spec.rb b/spec/unit/resource/apt_update_spec.rb
index 6b20092c56..c872061140 100644
--- a/spec/unit/resource/apt_update_spec.rb
+++ b/spec/unit/resource/apt_update_spec.rb
@@ -24,11 +24,6 @@ describe Chef::Resource::AptUpdate do
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:resource) { Chef::Resource::AptUpdate.new("update", run_context) }
- it "creates 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 "default frequency is set to be 1 day" do
expect(resource.frequency).to eql(86_400)
end
diff --git a/spec/unit/resource/bash_spec.rb b/spec/unit/resource/bash_spec.rb
index 56c36df1ce..10482002db 100644
--- a/spec/unit/resource/bash_spec.rb
+++ b/spec/unit/resource/bash_spec.rb
@@ -20,21 +20,18 @@ require "spec_helper"
describe Chef::Resource::Bash do
- before(:each) do
- @resource = Chef::Resource::Bash.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::Bash.new("fakey_fakerton") }
- it "should create a new Chef::Resource::Bash" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Bash)
+ it "is a subclass of Chef::Resource::Script" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Script)
end
- it "should have a resource name of :bash" do
- expect(@resource.resource_name).to eql(:bash)
+ it "has a resource name of :bash" do
+ expect(resource.resource_name).to eql(:bash)
end
- it "should have an interpreter of bash" do
- expect(@resource.interpreter).to eql("bash")
+ it "has an interpreter of bash" do
+ expect(resource.interpreter).to eql("bash")
end
end
diff --git a/spec/unit/resource/batch_spec.rb b/spec/unit/resource/batch_spec.rb
index e19ea15585..c161428a13 100644
--- a/spec/unit/resource/batch_spec.rb
+++ b/spec/unit/resource/batch_spec.rb
@@ -19,21 +19,18 @@
require "spec_helper"
describe Chef::Resource::Batch do
+ let(:node) { Chef::Node.new }
before(:each) do
- node = Chef::Node.new
-
node.default["kernel"] = Hash.new
node.default["kernel"][:machine] = :x86_64.to_s
node.automatic[:os] = "windows"
run_context = Chef::RunContext.new(node, nil, nil)
-
@resource = Chef::Resource::Batch.new("batch_unit_test", run_context)
-
end
- it "should create a new Chef::Resource::Batch" do
+ it "creates a new Chef::Resource::Batch" do
expect(@resource).to be_a_kind_of(Chef::Resource::Batch)
end
diff --git a/spec/unit/resource/cab_package_spec.rb b/spec/unit/resource/cab_package_spec.rb
index aa4890f171..87de446dd3 100644
--- a/spec/unit/resource/cab_package_spec.rb
+++ b/spec/unit/resource/cab_package_spec.rb
@@ -22,17 +22,33 @@ describe Chef::Resource::CabPackage do
let(:resource) { Chef::Resource::CabPackage.new("test_pkg") }
- it "creates a new Chef::Resource::CabPackage" do
- expect(resource).to be_a_kind_of(Chef::Resource)
+ it "is a subclass of Chef::Resource::Package" do
expect(resource).to be_a_kind_of(Chef::Resource::Package)
- expect(resource).to be_a_instance_of(Chef::Resource::CabPackage)
end
it "sets resource name as :cab_package" do
expect(resource.resource_name).to eql(:cab_package)
end
- it "coerce its name to a package_name" do
+ it "sets the default action as :install" do
+ expect(resource.action).to eql([:install])
+ end
+
+ it "coerces name property to package_name property" do
expect(resource.package_name).to eql("test_pkg")
end
+
+ it "coerces name property to a source property if source not provided" do
+ expect(resource.source).to end_with("test_pkg")
+ end
+
+ it "coerces name property to a source property if source not provided and package_name is" do
+ resource.package_name("package.cab")
+ expect(resource.source).to end_with("package.cab")
+ end
+
+ it "coerces source property if it does not looks like a path" do
+ resource.source("package.cab")
+ expect(resource.source).not_to eq("package.cab")
+ end
end
diff --git a/spec/unit/resource/chef_gem_spec.rb b/spec/unit/resource/chef_gem_spec.rb
index 2b09fb388f..0eac98c7d2 100644
--- a/spec/unit/resource/chef_gem_spec.rb
+++ b/spec/unit/resource/chef_gem_spec.rb
@@ -34,15 +34,15 @@ end
describe Chef::Resource::ChefGem, "gem_binary" do
let(:resource) { Chef::Resource::ChefGem.new("foo") }
- it "should raise an exception when gem_binary is set" do
+ it "raises an exception when gem_binary is set" do
expect { resource.gem_binary("/lol/cats/gem") }.to raise_error(ArgumentError)
end
- it "should set the gem_binary based on computing it from RbConfig" do
+ it "sets the gem_binary based on computing it from RbConfig" do
expect(resource.gem_binary).to eql("#{RbConfig::CONFIG['bindir']}/gem")
end
- it "should set compile_time to false by default" do
+ it "sets compile_time to false by default" do
expect(resource.compile_time).to be false
end
diff --git a/spec/unit/resource/chocolatey_package_spec.rb b/spec/unit/resource/chocolatey_package_spec.rb
index 9b433045c1..452373b571 100644
--- a/spec/unit/resource/chocolatey_package_spec.rb
+++ b/spec/unit/resource/chocolatey_package_spec.rb
@@ -22,50 +22,48 @@ describe Chef::Resource::ChocolateyPackage do
let(:resource) { Chef::Resource::ChocolateyPackage.new("fakey_fakerton") }
- it "should create a new Chef::Resource::ChocolateyPackage" do
- expect(resource).to be_a_kind_of(Chef::Resource)
+ it "is a subclass of Chef::Resource::Package" do
expect(resource).to be_a_kind_of(Chef::Resource::Package)
- expect(resource).to be_a_instance_of(Chef::Resource::ChocolateyPackage)
end
- it "should have a resource name of :python" do
+ it "has a resource name of :python" do
expect(resource.resource_name).to eql(:chocolatey_package)
end
- it "should coerce its name to a package_name array" do
+ it "coerces its name to a package_name array" do
expect(resource.package_name).to eql(["fakey_fakerton"])
end
- it "the package_name setter should coerce to arrays" do
+ it "the package_name setter coerces to arrays" do
resource.package_name("git")
expect(resource.package_name).to eql(["git"])
end
- it "the package_name setter should accept arrays" do
+ it "the package_name setter accepts 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
+ it "the name accepts arrays" do
resource = Chef::Resource::ChocolateyPackage.new(%w{git unzip})
expect(resource.package_name).to eql(%w{git unzip})
end
- it "the default version should be nil" do
+ it "the default version is nil" do
expect(resource.version).to eql(nil)
end
- it "the version setter should coerce to arrays" do
+ it "the version setter coerces 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
+ it "the version setter accepts arrays" 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
+ it "the default returns is 0" do
expect(resource.returns).to eql([0])
end
diff --git a/spec/unit/resource/conditional_spec.rb b/spec/unit/resource/conditional_spec.rb
index 0219945936..9a5f0a59bb 100644
--- a/spec/unit/resource/conditional_spec.rb
+++ b/spec/unit/resource/conditional_spec.rb
@@ -99,7 +99,7 @@ describe Chef::Resource::Conditional do
expect(@conditional.continue?).to be_falsey
end
- it "should log a warning" do
+ it "logs a warning" do
expect(Chef::Log).to receive(:warn).with("Command 'false' timed out")
@conditional.continue?
end
@@ -202,7 +202,7 @@ describe Chef::Resource::Conditional do
expect(@conditional.continue?).to be_truthy
end
- it "should log a warning" do
+ it "logs a warning" do
expect(Chef::Log).to receive(:warn).with("Command 'false' timed out")
@conditional.continue?
end
diff --git a/spec/unit/resource/cookbook_file_spec.rb b/spec/unit/resource/cookbook_file_spec.rb
index 05c37446a6..c6fdab3a1f 100644
--- a/spec/unit/resource/cookbook_file_spec.rb
+++ b/spec/unit/resource/cookbook_file_spec.rb
@@ -20,51 +20,45 @@
require "spec_helper"
describe Chef::Resource::CookbookFile do
- before do
- @cookbook_file = Chef::Resource::CookbookFile.new("sourcecode_tarball.tgz")
- end
-
- it "uses the name parameter for the source parameter" do
- expect(@cookbook_file.name).to eq("sourcecode_tarball.tgz")
- end
+ let(:resource) { Chef::Resource::CookbookFile.new("/foo/bar/sourcecode_tarball.tgz") }
- it "has a source parameter" do
- @cookbook_file.name("config_file.conf")
- expect(@cookbook_file.name).to eq("config_file.conf")
+ it "uses the basepath of the resourc ename for the source property" do
+ expect(resource.source).to eq("sourcecode_tarball.tgz")
end
- it "defaults to a nil cookbook parameter (current cookbook will be used)" do
- expect(@cookbook_file.cookbook).to be_nil
+ it "source property accepts Strings" do
+ resource.name("config_file.conf")
+ expect(resource.source).to eq("config_file.conf")
end
- it "has a cookbook parameter" do
- @cookbook_file.cookbook("munin")
- expect(@cookbook_file.cookbook).to eq("munin")
+ it "cookbook property defaults to nil (current cookbook will be used)" do
+ expect(resource.cookbook).to be_nil
end
- it "sets the provider to Chef::Provider::CookbookFile" do
- expect(@cookbook_file.provider).to eq(Chef::Provider::CookbookFile)
+ it "has a cookbook property that accepts Strings" do
+ resource.cookbook("munin")
+ expect(resource.cookbook).to eq("munin")
end
describe "when it has a backup number, group, mode, owner, source, checksum, and cookbook on nix or path, rights, deny_rights, checksum on windows" do
before do
if Chef::Platform.windows?
- @cookbook_file.path("C:/temp/origin/file.txt")
- @cookbook_file.rights(:read, "Everyone")
- @cookbook_file.deny_rights(:full_control, "Clumsy_Sam")
+ resource.path("C:/temp/origin/file.txt")
+ resource.rights(:read, "Everyone")
+ resource.deny_rights(:full_control, "Clumsy_Sam")
else
- @cookbook_file.path("/tmp/origin/file.txt")
- @cookbook_file.group("wheel")
- @cookbook_file.mode("0664")
- @cookbook_file.owner("root")
- @cookbook_file.source("/tmp/foo.txt")
- @cookbook_file.cookbook("/tmp/cookbooks/cooked.rb")
+ resource.path("/tmp/origin/file.txt")
+ resource.group("wheel")
+ resource.mode("0664")
+ resource.owner("root")
+ resource.source("/tmp/foo.txt")
+ resource.cookbook("/tmp/cookbooks/cooked.rb")
end
- @cookbook_file.checksum("1" * 64)
+ resource.checksum("1" * 64)
end
it "describes the state" do
- state = @cookbook_file.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
if Chef::Platform.windows?
puts state
expect(state[:rights]).to eq([{ :permissions => :read, :principals => "Everyone" }])
@@ -79,9 +73,9 @@ describe Chef::Resource::CookbookFile do
it "returns the path as its identity" do
if Chef::Platform.windows?
- expect(@cookbook_file.identity).to eq("C:/temp/origin/file.txt")
+ expect(resource.identity).to eq("C:/temp/origin/file.txt")
else
- expect(@cookbook_file.identity).to eq("/tmp/origin/file.txt")
+ expect(resource.identity).to eq("/tmp/origin/file.txt")
end
end
end
diff --git a/spec/unit/resource/cron_spec.rb b/spec/unit/resource/cron_spec.rb
index e2bfc321e8..91e0b05908 100644
--- a/spec/unit/resource/cron_spec.rb
+++ b/spec/unit/resource/cron_spec.rb
@@ -20,157 +20,149 @@
require "spec_helper"
describe Chef::Resource::Cron do
+ let(:resource) { Chef::Resource::Cron.new("cronify") }
- before(:each) do
- @resource = Chef::Resource::Cron.new("cronify")
+ it "has a name property" do
+ expect(resource.name).to eql("cronify")
end
- it "should create a new Chef::Resource::Cron" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Cron)
+ it "has a default action of [:create]" do
+ expect(resource.action).to eql([:create])
end
- it "should have a name" do
- expect(@resource.name).to eql("cronify")
+ it "accepts create or delete for action" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ expect { resource.action :lolcat }.to raise_error(ArgumentError)
end
- it "should have a default action of 'create'" do
- expect(@resource.action).to eql([:create])
+ it "allows you to set a command" do
+ resource.command "/bin/true"
+ expect(resource.command).to eql("/bin/true")
end
- it "should accept create or delete for action" do
- expect { @resource.action :create }.not_to raise_error
- expect { @resource.action :delete }.not_to raise_error
- expect { @resource.action :lolcat }.to raise_error(ArgumentError)
+ it "allows you to set a user" do
+ resource.user "daemon"
+ expect(resource.user).to eql("daemon")
end
- it "should allow you to set a command" do
- @resource.command "/bin/true"
- expect(@resource.command).to eql("/bin/true")
+ it "allows you to specify the minute" do
+ resource.minute "30"
+ expect(resource.minute).to eql("30")
end
- it "should allow you to set a user" do
- @resource.user "daemon"
- expect(@resource.user).to eql("daemon")
+ it "allows you to specify the hour" do
+ resource.hour "6"
+ expect(resource.hour).to eql("6")
end
- it "should allow you to specify the minute" do
- @resource.minute "30"
- expect(@resource.minute).to eql("30")
+ it "allows you to specify the day" do
+ resource.day "10"
+ expect(resource.day).to eql("10")
end
- it "should allow you to specify the hour" do
- @resource.hour "6"
- expect(@resource.hour).to eql("6")
+ it "allows you to specify the month" do
+ resource.month "10"
+ expect(resource.month).to eql("10")
end
- it "should allow you to specify the day" do
- @resource.day "10"
- expect(@resource.day).to eql("10")
+ it "allows you to specify the weekday" do
+ resource.weekday "2"
+ expect(resource.weekday).to eql("2")
end
- it "should allow you to specify the month" do
- @resource.month "10"
- expect(@resource.month).to eql("10")
+ it "allows you to specify the mailto variable" do
+ resource.mailto "test@example.com"
+ expect(resource.mailto).to eql("test@example.com")
end
- it "should allow you to specify the weekday" do
- @resource.weekday "2"
- expect(@resource.weekday).to eql("2")
+ it "allows you to specify the path" do
+ resource.path "/usr/bin:/usr/sbin"
+ expect(resource.path).to eql("/usr/bin:/usr/sbin")
end
- it "should allow you to specify the mailto variable" do
- @resource.mailto "test@example.com"
- expect(@resource.mailto).to eql("test@example.com")
+ it "allows you to specify the home directory" do
+ resource.home "/root"
+ expect(resource.home).to eql("/root")
end
- it "should allow you to specify the path" do
- @resource.path "/usr/bin:/usr/sbin"
- expect(@resource.path).to eql("/usr/bin:/usr/sbin")
+ it "allows you to specify the shell to run the command with" do
+ resource.shell "/bin/zsh"
+ expect(resource.shell).to eql("/bin/zsh")
end
- it "should allow you to specify the home directory" do
- @resource.home "/root"
- expect(@resource.home).to eql("/root")
- end
-
- it "should allow you to specify the shell to run the command with" do
- @resource.shell "/bin/zsh"
- expect(@resource.shell).to eql("/bin/zsh")
- end
-
- it "should allow you to specify environment variables hash" do
+ it "allows you to specify environment variables hash" do
env = { "TEST" => "LOL" }
- @resource.environment env
- expect(@resource.environment).to eql(env)
+ resource.environment env
+ expect(resource.environment).to eql(env)
end
- it "should allow * for all time and date values" do
+ it "allows * for all time and date values" do
%w{minute hour day month weekday}.each do |x|
- expect(@resource.send(x, "*")).to eql("*")
+ expect(resource.send(x, "*")).to eql("*")
end
end
- it "should allow ranges for all time and date values" do
+ it "allows ranges for all time and date values" do
%w{minute hour day month weekday}.each do |x|
- expect(@resource.send(x, "1-2,5")).to eql("1-2,5")
+ expect(resource.send(x, "1-2,5")).to eql("1-2,5")
end
end
- it "should have a default value of * for all time and date values" do
+ it "has a default value of * for all time and date values" do
%w{minute hour day month weekday}.each do |x|
- expect(@resource.send(x)).to eql("*")
+ expect(resource.send(x)).to eql("*")
end
end
- it "should have a default value of root for the user" do
- expect(@resource.user).to eql("root")
+ it "has a default value of root for the user" do
+ expect(resource.user).to eql("root")
end
- it "should reject any minute over 59" do
- expect { @resource.minute "60" }.to raise_error(RangeError)
+ it "rejects any minute over 59" do
+ expect { resource.minute "60" }.to raise_error(RangeError)
end
- it "should reject any hour over 23" do
- expect { @resource.hour "24" }.to raise_error(RangeError)
+ it "rejects any hour over 23" do
+ expect { resource.hour "24" }.to raise_error(RangeError)
end
- it "should reject any day over 31" do
- expect { @resource.day "32" }.to raise_error(RangeError)
+ it "rejects any day over 31" do
+ expect { resource.day "32" }.to raise_error(RangeError)
end
- it "should reject any month over 12" do
- expect { @resource.month "13" }.to raise_error(RangeError)
+ it "rejects any month over 12" do
+ expect { resource.month "13" }.to raise_error(RangeError)
end
describe "weekday" do
- it "should reject any weekday over 7" do
- expect { @resource.weekday "8" }.to raise_error(RangeError)
+ it "rejects any weekday over 7" do
+ expect { resource.weekday "8" }.to raise_error(RangeError)
end
- it "should reject any symbols which don't represent day of week" do
- expect { @resource.weekday :foo }.to raise_error(RangeError)
+ it "rejects any symbols which don't represent day of week" do
+ expect { resource.weekday :foo }.to raise_error(RangeError)
end
end
- it "should convert integer schedule values to a string" do
+ it "converts integer schedule values to a string" do
%w{minute hour day month weekday}.each do |x|
- expect(@resource.send(x, 5)).to eql("5")
+ expect(resource.send(x, 5)).to eql("5")
end
end
describe "when it has a time (minute, hour, day, month, weeekend) and user" do
before do
- @resource.command("tackle")
- @resource.minute("1")
- @resource.hour("2")
- @resource.day("3")
- @resource.month("4")
- @resource.weekday("5")
- @resource.user("root")
+ resource.command("tackle")
+ resource.minute("1")
+ resource.hour("2")
+ resource.day("3")
+ resource.month("4")
+ resource.weekday("5")
+ resource.user("root")
end
it "describes the state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:minute]).to eq("1")
expect(state[:hour]).to eq("2")
expect(state[:day]).to eq("3")
@@ -180,7 +172,7 @@ describe Chef::Resource::Cron do
end
it "returns the command as its identity" do
- expect(@resource.identity).to eq("tackle")
+ expect(resource.identity).to eq("tackle")
end
end
end
diff --git a/spec/unit/resource/csh_spec.rb b/spec/unit/resource/csh_spec.rb
index 864175fc85..3391bf84cf 100644
--- a/spec/unit/resource/csh_spec.rb
+++ b/spec/unit/resource/csh_spec.rb
@@ -20,21 +20,18 @@ require "spec_helper"
describe Chef::Resource::Csh do
- before(:each) do
- @resource = Chef::Resource::Csh.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::Csh.new("fakey_fakerton") }
- it "should create a new Chef::Resource::Csh" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Csh)
+ it "is a subclass of Chef::Resource::Script" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Script)
end
- it "should have a resource name of :csh" do
- expect(@resource.resource_name).to eql(:csh)
+ it "has a resource name of :csh" do
+ expect(resource.resource_name).to eql(:csh)
end
- it "should have an interpreter of csh" do
- expect(@resource.interpreter).to eql("csh")
+ it "has an interpreter of csh" do
+ expect(resource.interpreter).to eql("csh")
end
end
diff --git a/spec/unit/resource/deploy_revision_spec.rb b/spec/unit/resource/deploy_revision_spec.rb
deleted file mode 100644
index aa12b9595d..0000000000
--- a/spec/unit/resource/deploy_revision_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
-# 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::DeployRevision do
-
- static_provider_resolution(
- resource: Chef::Resource::DeployRevision,
- provider: Chef::Provider::Deploy::Revision,
- name: :deploy_revision,
- action: :deploy
- )
-
-end
-
-describe Chef::Resource::DeployBranch do
-
- static_provider_resolution(
- resource: Chef::Resource::DeployBranch,
- provider: Chef::Provider::Deploy::Revision,
- name: :deploy_branch,
- action: :deploy
- )
-
-end
diff --git a/spec/unit/resource/deploy_spec.rb b/spec/unit/resource/deploy_spec.rb
deleted file mode 100644
index e008d79c29..0000000000
--- a/spec/unit/resource/deploy_spec.rb
+++ /dev/null
@@ -1,283 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2008-2017, Chef Software Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "spec_helper"
-require "support/shared/unit/resource/static_provider_resolution"
-
-describe Chef::Resource::Deploy do
-
- static_provider_resolution(
- resource: Chef::Resource::Deploy,
- provider: Chef::Provider::Deploy::Timestamped,
- name: :deploy,
- action: :deploy
- )
-
- class << self
- def resource_has_a_string_attribute(attr_name)
- it "has a String attribute for #{attr_name}" do
- @resource.send(attr_name, "this is a string")
- expect(@resource.send(attr_name)).to eql("this is a string")
- expect { @resource.send(attr_name, 8675309) }.to raise_error(ArgumentError)
- end
- end
-
- def resource_has_a_boolean_attribute(attr_name, opts = { :defaults_to => false })
- it "has a Boolean attribute for #{attr_name}" do
- expect(@resource.send(attr_name)).to eql(opts[:defaults_to])
- @resource.send(attr_name, !opts[:defaults_to])
- expect(@resource.send(attr_name)).to eql( !opts[:defaults_to] )
- end
- end
-
- def resource_has_a_callback_attribute(attr_name)
- it "has a Callback attribute #{attr_name}" do
- callback_block = lambda { :noop }
- expect { @resource.send(attr_name, &callback_block) }.not_to raise_error
- expect(@resource.send(attr_name)).to eq(callback_block)
- callback_file = "path/to/callback.rb"
- expect { @resource.send(attr_name, callback_file) }.not_to raise_error
- expect(@resource.send(attr_name)).to eq(callback_file)
- expect { @resource.send(attr_name, :this_is_fail) }.to raise_error(ArgumentError)
- end
- end
- end
-
- before do
- @resource = Chef::Resource::Deploy.new("/my/deploy/dir")
- end
-
- resource_has_a_string_attribute(:repo)
- resource_has_a_string_attribute(:deploy_to)
- resource_has_a_string_attribute(:role)
- resource_has_a_string_attribute(:restart_command)
- resource_has_a_string_attribute(:migration_command)
- resource_has_a_string_attribute(:user)
- resource_has_a_string_attribute(:group)
- resource_has_a_string_attribute(:repository_cache)
- resource_has_a_string_attribute(:copy_exclude)
- resource_has_a_string_attribute(:revision)
- resource_has_a_string_attribute(:remote)
- resource_has_a_string_attribute(:git_ssh_wrapper)
- resource_has_a_string_attribute(:svn_username)
- resource_has_a_string_attribute(:svn_password)
- resource_has_a_string_attribute(:svn_arguments)
- resource_has_a_string_attribute(:svn_info_args)
-
- resource_has_a_boolean_attribute(:migrate, :defaults_to => false)
- resource_has_a_boolean_attribute(:enable_submodules, :defaults_to => false)
- resource_has_a_boolean_attribute(:shallow_clone, :defaults_to => false)
-
- it "uses the first argument as the deploy directory" do
- expect(@resource.deploy_to).to eql("/my/deploy/dir")
- end
-
- # For git, any revision, branch, tag, whatever is resolved to a SHA1 ref.
- # For svn, the branch is included in the repo URL.
- # Therefore, revision and branch ARE NOT SEPARATE THINGS
- it "aliases #revision as #branch" do
- @resource.branch "stable"
- expect(@resource.revision).to eql("stable")
- end
-
- it "takes the SCM resource to use as a constant, and defaults to git" do
- expect(@resource.scm_provider).to eql(Chef::Provider::Git)
- @resource.scm_provider Chef::Provider::Subversion
- expect(@resource.scm_provider).to eql(Chef::Provider::Subversion)
- end
-
- it "allows scm providers to be set via symbol" do
- expect(@resource.scm_provider).to eq(Chef::Provider::Git)
- @resource.scm_provider :subversion
- expect(@resource.scm_provider).to eq(Chef::Provider::Subversion)
- end
-
- it "allows scm providers to be set via string" do
- expect(@resource.scm_provider).to eq(Chef::Provider::Git)
- @resource.scm_provider "subversion"
- expect(@resource.scm_provider).to eq(Chef::Provider::Subversion)
- end
-
- it "has a boolean attribute for svn_force_export defaulting to false" do
- expect(@resource.svn_force_export).to be_falsey
- @resource.svn_force_export true
- expect(@resource.svn_force_export).to be_truthy
- expect { @resource.svn_force_export(10053) }.to raise_error(ArgumentError)
- end
-
- it "takes arbitrary environment variables in a hash" do
- @resource.environment "RAILS_ENV" => "production"
- expect(@resource.environment).to eq({ "RAILS_ENV" => "production" })
- end
-
- it "takes string arguments to environment for backwards compat, setting RAILS_ENV, RACK_ENV, and MERB_ENV" do
- @resource.environment "production"
- expect(@resource.environment).to eq({ "RAILS_ENV" => "production", "RACK_ENV" => "production", "MERB_ENV" => "production" })
- end
-
- it "sets destination to $deploy_to/shared/$repository_cache" do
- expect(@resource.destination).to eql("/my/deploy/dir/shared/cached-copy")
- end
-
- it "sets shared_path to $deploy_to/shared" do
- expect(@resource.shared_path).to eql("/my/deploy/dir/shared")
- end
-
- it "sets current_path to $deploy_to/current" do
- expect(@resource.current_path).to eql("/my/deploy/dir/current")
- end
-
- it "gets the current_path correct even if the shared_path is set (regression test)" do
- @resource.shared_path
- expect(@resource.current_path).to eql("/my/deploy/dir/current")
- end
-
- it "allows depth to be set via integer" do
- expect(@resource.depth).to be_nil
- @resource.depth 1
- expect(@resource.depth).to eql(1)
- end
-
- it "gives #depth as 5 if shallow clone is true, nil otherwise" do
- expect(@resource.depth).to be_nil
- @resource.shallow_clone true
- expect(@resource.depth).to eql(5)
- end
-
- it "aliases repo as repository" do
- @resource.repository "git@github.com/opcode/cookbooks.git"
- expect(@resource.repo).to eql("git@github.com/opcode/cookbooks.git")
- end
-
- it "aliases git_ssh_wrapper as ssh_wrapper" do
- @resource.ssh_wrapper "git_my_repo.sh"
- expect(@resource.git_ssh_wrapper).to eql("git_my_repo.sh")
- end
-
- it "has an Array attribute purge_before_symlink, default: log, tmp/pids, public/system" do
- expect(@resource.purge_before_symlink).to eq(%w{ log tmp/pids public/system })
- @resource.purge_before_symlink %w{foo bar baz}
- expect(@resource.purge_before_symlink).to eq(%w{foo bar baz})
- end
-
- it "has an Array attribute create_dirs_before_symlink, default: tmp, public, config" do
- expect(@resource.create_dirs_before_symlink).to eq(%w{tmp public config})
- @resource.create_dirs_before_symlink %w{foo bar baz}
- expect(@resource.create_dirs_before_symlink).to eq(%w{foo bar baz})
- end
-
- it 'has a Hash attribute symlinks, default: {"system" => "public/system", "pids" => "tmp/pids", "log" => "log"}' do
- default = { "system" => "public/system", "pids" => "tmp/pids", "log" => "log" }
- expect(@resource.symlinks).to eq(default)
- @resource.symlinks "foo" => "bar/baz"
- expect(@resource.symlinks).to eq({ "foo" => "bar/baz" })
- end
-
- it 'has a Hash attribute symlink_before_migrate, default "config/database.yml" => "config/database.yml"' do
- expect(@resource.symlink_before_migrate).to eq({ "config/database.yml" => "config/database.yml" })
- @resource.symlink_before_migrate "wtf?" => "wtf is going on"
- expect(@resource.symlink_before_migrate).to eq({ "wtf?" => "wtf is going on" })
- end
-
- resource_has_a_callback_attribute :before_migrate
- resource_has_a_callback_attribute :before_symlink
- resource_has_a_callback_attribute :before_restart
- resource_has_a_callback_attribute :after_restart
-
- it "aliases restart_command as restart" do
- @resource.restart "foobaz"
- expect(@resource.restart_command).to eq("foobaz")
- end
-
- it "takes a block for the restart parameter" do
- restart_like_this = lambda { p :noop }
- @resource.restart(&restart_like_this)
- expect(@resource.restart).to eq(restart_like_this)
- end
-
- it "allows providers to be set with a full class name" do
- @resource.provider Chef::Provider::Deploy::Timestamped
- expect(@resource.provider).to eq(Chef::Provider::Deploy::Timestamped)
- end
-
- it "allows deploy providers to be set via symbol" do
- @resource.provider :deploy_revision
- expect(@resource.provider).to eq(Chef::Provider::Deploy::Revision)
- end
-
- it "allows deploy providers to be set via string" do
- @resource.provider "deploy_revision"
- expect(@resource.provider).to eq(Chef::Provider::Deploy::Revision)
- end
-
- it "defaults keep_releases to 5" do
- expect(@resource.keep_releases).to eq(5)
- end
-
- it "allows keep_releases to be set via integer" do
- @resource.keep_releases 10
- expect(@resource.keep_releases).to eq(10)
- end
-
- it "enforces a minimum keep_releases of 1" do
- @resource.keep_releases 0
- expect(@resource.keep_releases).to eq(1)
- end
-
- describe "when it has a timeout attribute" do
- let(:ten_seconds) { 10 }
- before { @resource.timeout(ten_seconds) }
- it "stores this timeout" do
- expect(@resource.timeout).to eq(ten_seconds)
- end
- end
-
- describe "when it has no timeout attribute" do
- it "should have no default timeout" do
- expect(@resource.timeout).to be_nil
- end
- end
-
- describe "when it has meta application root, revision, user, group,
- scm provider, repository cache, environment, simlinks and migrate" do
- before do
- @resource.repository("http://uri.org")
- @resource.deploy_to("/")
- @resource.revision("1.2.3")
- @resource.user("root")
- @resource.group("pokemon")
- @resource.scm_provider(Chef::Provider::Git)
- @resource.repository_cache("cached-copy")
- @resource.environment({ "SUDO" => "TRUE" })
- @resource.symlinks({ "system" => "public/system" })
- @resource.migrate(false)
-
- end
-
- it "describes its state" do
- state = @resource.state_for_resource_reporter
- expect(state[:deploy_to]).to eq("/")
- expect(state[:revision]).to eq("1.2.3")
- end
-
- it "returns the repository URI as its identity" do
- expect(@resource.identity).to eq("http://uri.org")
- end
- end
-
-end
diff --git a/spec/unit/resource/directory_spec.rb b/spec/unit/resource/directory_spec.rb
index b3a0134024..778e54ccb6 100644
--- a/spec/unit/resource/directory_spec.rb
+++ b/spec/unit/resource/directory_spec.rb
@@ -20,63 +20,55 @@
require "spec_helper"
describe Chef::Resource::Directory do
+ let(:resource) { Chef::Resource::Directory.new("fakey_fakerton") }
- before(:each) do
- @resource = Chef::Resource::Directory.new("fakey_fakerton")
+ it "has a name property" do
+ expect(resource.name).to eql("fakey_fakerton")
end
- it "should create a new Chef::Resource::Directory" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Directory)
+ it "has a default action of 'create'" do
+ expect(resource.action).to eql([:create])
end
- it "should have a name" do
- expect(@resource.name).to eql("fakey_fakerton")
+ it "accepts create or delete for action" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ expect { resource.action :blues }.to raise_error(ArgumentError)
end
- it "should have a default action of 'create'" do
- expect(@resource.action).to eql([:create])
+ it "uses the object name as the path by default" do
+ expect(resource.path).to eql("fakey_fakerton")
end
- it "should accept create or delete for action" do
- expect { @resource.action :create }.not_to raise_error
- expect { @resource.action :delete }.not_to raise_error
- expect { @resource.action :blues }.to raise_error(ArgumentError)
+ it "accepts a string as the path" do
+ expect { resource.path "/tmp" }.not_to raise_error
+ expect(resource.path).to eql("/tmp")
+ expect { resource.path Hash.new }.to raise_error(ArgumentError)
end
- it "should use the object name as the path by default" do
- expect(@resource.path).to eql("fakey_fakerton")
- end
-
- it "should accept a string as the path" do
- expect { @resource.path "/tmp" }.not_to raise_error
- expect(@resource.path).to eql("/tmp")
- expect { @resource.path Hash.new }.to raise_error(ArgumentError)
- end
-
- it "should allow you to have specify whether the action is recursive with true/false" do
- expect { @resource.recursive true }.not_to raise_error
- expect { @resource.recursive false }.not_to raise_error
- expect { @resource.recursive "monkey" }.to raise_error(ArgumentError)
+ it "allows you to have specify whether the action is recursive with true/false" do
+ expect { resource.recursive true }.not_to raise_error
+ expect { resource.recursive false }.not_to raise_error
+ expect { resource.recursive "monkey" }.to raise_error(ArgumentError)
end
describe "when it has group, mode, and owner" do
before do
- @resource.path("/tmp/foo/bar/")
- @resource.group("wheel")
- @resource.mode("0664")
- @resource.owner("root")
+ resource.path("/tmp/foo/bar/")
+ resource.group("wheel")
+ resource.mode("0664")
+ resource.owner("root")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:group]).to eq("wheel")
expect(state[:mode]).to eq("0664")
expect(state[:owner]).to eq("root")
end
it "returns the directory path as its identity" do
- expect(@resource.identity).to eq("/tmp/foo/bar/")
+ expect(resource.identity).to eq("/tmp/foo/bar/")
end
end
end
diff --git a/spec/unit/resource/dnf_package_spec.rb b/spec/unit/resource/dnf_package_spec.rb
index 0cc673d897..21979b05c3 100644
--- a/spec/unit/resource/dnf_package_spec.rb
+++ b/spec/unit/resource/dnf_package_spec.rb
@@ -32,68 +32,62 @@ describe Chef::Resource::DnfPackage, "initialize" do
end
describe Chef::Resource::DnfPackage, "arch" do
- before(:each) do
- @resource = Chef::Resource::DnfPackage.new("foo")
- end
+ let(:resource) { Chef::Resource::DnfPackage.new("foo") }
- it "should set the arch variable to whatever is passed in" do
- @resource.arch("i386")
- expect(@resource.arch).to eql(["i386"])
+ it "sets 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
+ let(:resource) { Chef::Resource::DnfPackage.new("foo") }
- it "should default the flush timing to false" do
+ it "defaults the flush timing to false" do
flush_hash = { :before => false, :after => false }
- expect(@resource.flush_cache).to eq(flush_hash)
+ expect(resource.flush_cache).to eq(flush_hash)
end
- it "should allow you to set the flush timing with an array" do
+ it "allows 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)
+ 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
+ it "allows 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)
+ 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 })
+ it "allows '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 })
+ it "allows '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 })
+ it "allows ':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 })
+ it "allows ':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
+ let(:resource) { Chef::Resource::DnfPackage.new("foo") }
- it "should allow you to specify whether allow_downgrade is true or false" do
+ it "allows 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
+ 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/env_spec.rb b/spec/unit/resource/env_spec.rb
index 1c63ab519f..61c40e33e8 100644
--- a/spec/unit/resource/env_spec.rb
+++ b/spec/unit/resource/env_spec.rb
@@ -20,65 +20,57 @@
require "spec_helper"
describe Chef::Resource::Env do
+ let(:resource) { Chef::Resource::Env.new("FOO") }
- before(:each) do
- @resource = Chef::Resource::Env.new("FOO")
+ it "has a name property" do
+ expect(resource.name).to eql("FOO")
end
- it "should create a new Chef::Resource::Env" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Env)
- end
-
- it "should have a name" do
- expect(@resource.name).to eql("FOO")
- end
-
- it "should have a default action of 'create'" do
- expect(@resource.action).to eql([:create])
+ it "has a default action of 'create'" do
+ expect(resource.action).to eql([:create])
end
{ :create => false, :delete => false, :modify => false, :flibber => true }.each do |action, bad_value|
it "should #{bad_value ? 'not' : ''} accept #{action}" do
if bad_value
- expect { @resource.action action }.to raise_error(ArgumentError)
+ expect { resource.action action }.to raise_error(ArgumentError)
else
- expect { @resource.action action }.not_to raise_error
+ expect { resource.action action }.not_to raise_error
end
end
end
- it "should use the object name as the key_name by default" do
- expect(@resource.key_name).to eql("FOO")
+ it "uses the object name as the key_name by default" do
+ expect(resource.key_name).to eql("FOO")
end
- it "should accept a string as the env value via 'value'" do
- expect { @resource.value "bar" }.not_to raise_error
+ it "accepts a string as the env value via 'value'" do
+ expect { resource.value "bar" }.not_to raise_error
end
- it "should not accept a Hash for the env value via 'to'" do
- expect { @resource.value Hash.new }.to raise_error(ArgumentError)
+ it "does not accept a Hash for the env value via 'to'" do
+ expect { resource.value Hash.new }.to raise_error(ArgumentError)
end
- it "should allow you to set an env value via 'to'" do
- @resource.value "bar"
- expect(@resource.value).to eql("bar")
+ it "allows you to set an env value via 'to'" do
+ resource.value "bar"
+ expect(resource.value).to eql("bar")
end
describe "when it has key name and value" do
before do
- @resource.key_name("charmander")
- @resource.value("level7")
- @resource.delim("hi")
+ resource.key_name("charmander")
+ resource.value("level7")
+ resource.delim("hi")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:value]).to eq("level7")
end
it "returns the key name as its identity" do
- expect(@resource.identity).to eq("charmander")
+ expect(resource.identity).to eq("charmander")
end
end
diff --git a/spec/unit/resource/erl_call_spec.rb b/spec/unit/resource/erl_call_spec.rb
deleted file mode 100644
index 6d1f45ec63..0000000000
--- a/spec/unit/resource/erl_call_spec.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Author:: Joe Williams (<joe@joetify.com>)
-# Author:: Tyler Cloke (<tyler@chef.io>)
-# Copyright:: Copyright 2009-2016, Joe Williams
-# 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::ErlCall do
-
- before(:each) do
- @resource = Chef::Resource::ErlCall.new("fakey_fakerton")
- end
-
- it "should create a new Chef::Resource::ErlCall" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::ErlCall)
- end
-
- it "should have a resource name of :erl_call" do
- expect(@resource.resource_name).to eql(:erl_call)
- end
-
- it "should have a default action of run" do
- expect(@resource.action).to eql([:run])
- end
-
- it "should accept run as an action" do
- expect { @resource.action :run }.not_to raise_error
- end
-
- it "should allow you to set the code attribute" do
- @resource.code "q()."
- expect(@resource.code).to eql("q().")
- end
-
- it "should allow you to set the cookie attribute" do
- @resource.cookie "nomnomnom"
- expect(@resource.cookie).to eql("nomnomnom")
- end
-
- it "should allow you to set the distributed attribute" do
- @resource.distributed true
- expect(@resource.distributed).to eql(true)
- end
-
- it "should allow you to set the name_type attribute" do
- @resource.name_type "sname"
- expect(@resource.name_type).to eql("sname")
- end
-
- it "should allow you to set the node_name attribute" do
- @resource.node_name "chef@erlang"
- expect(@resource.node_name).to eql("chef@erlang")
- end
-
- describe "when it has cookie and node_name" do
- before do
- @resource.code("erl-call:function()")
- @resource.cookie("cookie")
- @resource.node_name("raster")
- end
-
- it "returns the code as its identity" do
- expect(@resource.identity).to eq("erl-call:function()")
- end
- end
-end
diff --git a/spec/unit/resource/execute_spec.rb b/spec/unit/resource/execute_spec.rb
index 575c80ba2f..c99e87b351 100644
--- a/spec/unit/resource/execute_spec.rb
+++ b/spec/unit/resource/execute_spec.rb
@@ -24,7 +24,7 @@ describe Chef::Resource::Execute do
let(:execute_resource) { Chef::Resource::Execute.new(resource_instance_name) }
it_behaves_like "an execute resource"
- it "default guard interpreter should be :execute interpreter" do
+ it "default guard interpreter is :execute interpreter" do
expect(execute_resource.guard_interpreter).to be(:execute)
end
@@ -59,13 +59,13 @@ describe Chef::Resource::Execute do
shared_examples_for "it received valid credentials" do
describe "the validation method" do
- it "should not raise an error" do
+ it "does 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
+ it "correctly translates 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)
@@ -76,7 +76,7 @@ describe Chef::Resource::Execute do
shared_examples_for "it received invalid credentials" do
describe "the validation method" do
- it "should raise an error" do
+ it "raises an error" do
expect { execute_resource.validate_identity_platform(username, password, domain, elevated) }.to raise_error(ArgumentError)
end
end
@@ -84,7 +84,7 @@ describe Chef::Resource::Execute do
shared_examples_for "it received invalid username and domain" do
describe "the validation method" do
- it "should raise an error" do
+ it "raises an error" do
expect { execute_resource.qualify_user(username, password, domain) }.to raise_error(ArgumentError)
end
end
@@ -92,7 +92,7 @@ describe Chef::Resource::Execute do
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
+ it "raises an error" do
expect { execute_resource.validate_identity_platform(username, password, domain) }.to raise_error(Chef::Exceptions::UnsupportedPlatform)
end
end
diff --git a/spec/unit/resource/file/verification_spec.rb b/spec/unit/resource/file/verification_spec.rb
index feacd715a4..e46040268a 100644
--- a/spec/unit/resource/file/verification_spec.rb
+++ b/spec/unit/resource/file/verification_spec.rb
@@ -66,6 +66,11 @@ describe Chef::Resource::File::Verification do
v = Chef::Resource::File::Verification.new(parent_resource, nil, {}, &f_block)
expect(v.verify(temp_path)).to eq(false)
end
+
+ it "responds to to_s" do
+ v = Chef::Resource::File::Verification.new(parent_resource, nil, {}) {}
+ expect(v.to_s).to eq("<Proc>")
+ end
end
context "with a verification command(String)" do
@@ -110,23 +115,32 @@ describe Chef::Resource::File::Verification do
v = Chef::Resource::File::Verification.new(parent_resource, "true", {})
expect(v.verify(temp_path)).to eq(true)
end
+
+ it "responds to to_s" do
+ v = Chef::Resource::File::Verification.new(parent_resource, "some command --here", {})
+ expect(v.to_s).to eq("some command --here")
+ end
end
context "with a named verification(Symbol)" do
+ let(:registered_verification) { double("registered_verification") }
+ subject { described_class.new(parent_resource, :cats, {}) }
before(:each) do
class Chef::Resource::File::Verification::Turtle < Chef::Resource::File::Verification
provides :cats
def verify(path, opts)
end
end
+ allow(Chef::Resource::File::Verification::Turtle).to receive(:new).and_return(registered_verification)
end
it "delegates to the registered verification" do
- registered_verification = double()
- allow(Chef::Resource::File::Verification::Turtle).to receive(:new).and_return(registered_verification)
- v = Chef::Resource::File::Verification.new(parent_resource, :cats, {})
expect(registered_verification).to receive(:verify).with(temp_path, {})
- v.verify(temp_path, {})
+ subject.verify(temp_path, {})
+ end
+
+ it "responds to to_s" do
+ expect(subject.to_s).to eq(":cats (Chef::Resource::File::Verification::Turtle)")
end
end
end
diff --git a/spec/unit/resource/file_spec.rb b/spec/unit/resource/file_spec.rb
index 4004798dad..f2dea066ad 100644
--- a/spec/unit/resource/file_spec.rb
+++ b/spec/unit/resource/file_spec.rb
@@ -20,88 +20,86 @@ require "spec_helper"
describe Chef::Resource::File do
- before(:each) do
- @resource = Chef::Resource::File.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::File.new("fakey_fakerton") }
- it "should have a name" do
- expect(@resource.name).to eql("fakey_fakerton")
+ it "has a name property" do
+ expect(resource.name).to eql("fakey_fakerton")
end
- it "should have a default action of 'create'" do
- expect(@resource.action).to eql([:create])
+ it "has a default action of 'create'" do
+ expect(resource.action).to eql([:create])
end
- it "should have a default content of nil" do
- expect(@resource.content).to be_nil
+ it "has a default content of nil" do
+ expect(resource.content).to be_nil
end
- it "should be set to back up 5 files by default" do
- expect(@resource.backup).to eql(5)
+ it "is set to back up 5 files by default" do
+ expect(resource.backup).to eql(5)
end
- it "should only accept strings for content" do
- expect { @resource.content 5 }.to raise_error(ArgumentError)
- expect { @resource.content :foo }.to raise_error(ArgumentError)
- expect { @resource.content "hello" => "there" }.to raise_error(ArgumentError)
- expect { @resource.content "hi" }.not_to raise_error
+ it "only accept strings for content" do
+ expect { resource.content 5 }.to raise_error(ArgumentError)
+ expect { resource.content :foo }.to raise_error(ArgumentError)
+ expect { resource.content "hello" => "there" }.to raise_error(ArgumentError)
+ expect { resource.content "hi" }.not_to raise_error
end
- it "should only accept false or a number for backup" do
- expect { @resource.backup true }.to raise_error(ArgumentError)
- expect { @resource.backup false }.not_to raise_error
- expect { @resource.backup 10 }.not_to raise_error
- expect { @resource.backup "blues" }.to raise_error(ArgumentError)
+ it "only accept false or a number for backup" do
+ expect { resource.backup true }.to raise_error(ArgumentError)
+ expect { resource.backup false }.not_to raise_error
+ expect { resource.backup 10 }.not_to raise_error
+ expect { resource.backup "blues" }.to raise_error(ArgumentError)
end
- it "should accept a sha256 for checksum" do
- expect { @resource.checksum "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa" }.not_to raise_error
- expect { @resource.checksum "monkey!" }.to raise_error(ArgumentError)
+ it "accepts a sha256 for checksum" do
+ expect { resource.checksum "0fd012fdc96e96f8f7cf2046522a54aed0ce470224513e45da6bc1a17a4924aa" }.not_to raise_error
+ expect { resource.checksum "monkey!" }.to raise_error(ArgumentError)
end
- it "should accept create, delete or touch for action" do
- expect { @resource.action :create }.not_to raise_error
- expect { @resource.action :delete }.not_to raise_error
- expect { @resource.action :touch }.not_to raise_error
- expect { @resource.action :blues }.to raise_error(ArgumentError)
+ it "accepts create, delete or touch for action" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ expect { resource.action :touch }.not_to raise_error
+ expect { resource.action :blues }.to raise_error(ArgumentError)
end
- it "should accept a block, symbol, or string for verify" do
- expect { @resource.verify {} }.not_to raise_error
- expect { @resource.verify "" }.not_to raise_error
- expect { @resource.verify :json }.not_to raise_error
- expect { @resource.verify true }.to raise_error(ArgumentError)
- expect { @resource.verify false }.to raise_error(ArgumentError)
+ it "accepts a block, symbol, or string for verify" do
+ expect { resource.verify {} }.not_to raise_error
+ expect { resource.verify "" }.not_to raise_error
+ expect { resource.verify :json }.not_to raise_error
+ expect { resource.verify true }.to raise_error(ArgumentError)
+ expect { resource.verify false }.to raise_error(ArgumentError)
end
- it "should accept multiple verify statements" do
- @resource.verify "foo"
- @resource.verify "bar"
- @resource.verify.length == 2
+ it "accepts multiple verify statements" do
+ resource.verify "foo"
+ resource.verify "bar"
+ resource.verify.length == 2
end
- it "should use the object name as the path by default" do
- expect(@resource.path).to eql("fakey_fakerton")
+ it "uses the object name as the path by default" do
+ expect(resource.path).to eql("fakey_fakerton")
end
- it "should accept a string as the path" do
- expect { @resource.path "/tmp" }.not_to raise_error
- expect(@resource.path).to eql("/tmp")
- expect { @resource.path Hash.new }.to raise_error(ArgumentError)
+ it "accepts a string as the path" do
+ expect { resource.path "/tmp" }.not_to raise_error
+ expect(resource.path).to eql("/tmp")
+ expect { resource.path Hash.new }.to raise_error(ArgumentError)
end
describe "when it has a path, owner, group, mode, and checksum" do
before do
- @resource.path("/tmp/foo.txt")
- @resource.owner("root")
- @resource.group("wheel")
- @resource.mode("0644")
- @resource.checksum("1" * 64)
+ resource.path("/tmp/foo.txt")
+ resource.owner("root")
+ resource.group("wheel")
+ resource.mode("0644")
+ resource.checksum("1" * 64)
end
context "on unix", :unix_only do
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:owner]).to eq("root")
expect(state[:group]).to eq("wheel")
expect(state[:mode]).to eq("0644")
@@ -110,21 +108,20 @@ describe Chef::Resource::File do
end
it "returns the file path as its identity" do
- expect(@resource.identity).to eq("/tmp/foo.txt")
+ expect(resource.identity).to eq("/tmp/foo.txt")
end
end
describe "when access controls are set on windows", :windows_only => true do
before do
- @resource.rights :read, "Everyone"
- @resource.rights :full_control, "DOMAIN\User"
+ resource.rights :read, "Everyone"
+ resource.rights :full_control, "DOMAIN\User"
end
it "describes its state including windows ACL attributes" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:rights]).to eq([ { :permissions => :read, :principals => "Everyone" },
{ :permissions => :full_control, :principals => "DOMAIN\User" } ])
end
end
-
end
diff --git a/spec/unit/resource/freebsd_package_spec.rb b/spec/unit/resource/freebsd_package_spec.rb
index ce4300497e..4a223eb507 100644
--- a/spec/unit/resource/freebsd_package_spec.rb
+++ b/spec/unit/resource/freebsd_package_spec.rb
@@ -22,64 +22,63 @@ require "spec_helper"
require "ostruct"
describe Chef::Resource::FreebsdPackage do
- before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @resource = Chef::Resource::FreebsdPackage.new("foo", @run_context)
- end
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:resource) { Chef::Resource::FreebsdPackage.new("foo", run_context) }
describe "Initialization" do
- it "should return a Chef::Resource::FreebsdPackage" do
- expect(@resource).to be_a_kind_of(Chef::Resource::FreebsdPackage)
+
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
end
- it "should set the resource_name to :freebsd_package" do
- expect(@resource.resource_name).to eql(:freebsd_package)
+ it "sets the resource_name to :freebsd_package" do
+ expect(resource.resource_name).to eql(:freebsd_package)
end
- it "should not set the provider" do
- expect(@resource.provider).to be_nil
+ it "does not set the provider" do
+ expect(resource.provider).to be_nil
end
end
describe "Assigning provider after creation" do
describe "if ports specified as source" do
- it "should be Freebsd::Port" do
- @resource.source("ports")
- @resource.after_created
- expect(@resource.provider).to eq(Chef::Provider::Package::Freebsd::Port)
+ it "is Freebsd::Port" do
+ resource.source("ports")
+ resource.after_created
+ expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Port)
end
end
describe "if freebsd_version is greater than or equal to 1000017" do
- it "should be Freebsd::Pkgng" do
+ it "is Freebsd::Pkgng" do
[1000017, 1000018, 1000500, 1001001, 1100000].each do |freebsd_version|
- @node.automatic_attrs[:os_version] = freebsd_version
- @resource.after_created
- expect(@resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
+ node.automatic_attrs[:os_version] = freebsd_version
+ resource.after_created
+ expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
end
end
end
describe "if pkgng enabled" do
- it "should be Freebsd::Pkgng" do
+ it "is Freebsd::Pkgng" do
pkg_enabled = OpenStruct.new(:stdout => "yes\n")
- allow(@resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", :env => nil).and_return(pkg_enabled)
- @resource.after_created
- expect(@resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
+ allow(resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", :env => nil).and_return(pkg_enabled)
+ resource.after_created
+ expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkgng)
end
end
describe "if freebsd_version is less than 1000017 and pkgng not enabled" do
- it "should be Freebsd::Pkg" do
+ it "is Freebsd::Pkg" do
pkg_enabled = OpenStruct.new(:stdout => "\n")
- allow(@resource).to receive(:shell_out!).with("make", "-V", "WITH_PKGNG", :env => nil).and_return(pkg_enabled)
+ 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
- @resource.after_created
- expect(@resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkg)
+ node.automatic_attrs[:os_version] = freebsd_version
+ resource.after_created
+ expect(resource.provider).to eq(Chef::Provider::Package::Freebsd::Pkg)
end
end
end
diff --git a/spec/unit/resource/gem_package_spec.rb b/spec/unit/resource/gem_package_spec.rb
index a1571ab9bb..bee7ba9de4 100644
--- a/spec/unit/resource/gem_package_spec.rb
+++ b/spec/unit/resource/gem_package_spec.rb
@@ -31,12 +31,10 @@ describe Chef::Resource::GemPackage, "initialize" do
end
describe Chef::Resource::GemPackage, "gem_binary" do
- before(:each) do
- @resource = Chef::Resource::GemPackage.new("foo")
- end
+ let(:resource) { Chef::Resource::GemPackage.new("foo") }
- it "should set the gem_binary variable to whatever is passed in" do
- @resource.gem_binary("/opt/local/bin/gem")
- expect(@resource.gem_binary).to eql("/opt/local/bin/gem")
+ it "sets the gem_binary variable to whatever is passed in" do
+ resource.gem_binary("/opt/local/bin/gem")
+ expect(resource.gem_binary).to eql("/opt/local/bin/gem")
end
end
diff --git a/spec/unit/resource/git_spec.rb b/spec/unit/resource/git_spec.rb
index 15c1e54f25..1883595617 100644
--- a/spec/unit/resource/git_spec.rb
+++ b/spec/unit/resource/git_spec.rb
@@ -28,23 +28,20 @@ describe Chef::Resource::Git do
action: :sync
)
- before(:each) do
- @git = Chef::Resource::Git.new("my awesome webapp")
- end
+ let(:resource) { Chef::Resource::Git.new("my awesome webapp") }
- it "is a kind of Scm Resource" do
- expect(@git).to be_a_kind_of(Chef::Resource::Scm)
- expect(@git).to be_an_instance_of(Chef::Resource::Git)
+ it "is a subclass of Chef::Resource::Scm" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Scm)
end
it "uses aliases revision as branch" do
- @git.branch "HEAD"
- expect(@git.revision).to eql("HEAD")
+ resource.branch "HEAD"
+ expect(resource.revision).to eql("HEAD")
end
it "aliases revision as reference" do
- @git.reference "v1.0 tag"
- expect(@git.revision).to eql("v1.0 tag")
+ resource.reference "v1.0 tag"
+ expect(resource.revision).to eql("v1.0 tag")
end
end
diff --git a/spec/unit/resource/group_spec.rb b/spec/unit/resource/group_spec.rb
index 8772f37a2b..e850361beb 100644
--- a/spec/unit/resource/group_spec.rb
+++ b/spec/unit/resource/group_spec.rb
@@ -20,143 +20,128 @@
require "spec_helper"
describe Chef::Resource::Group, "initialize" do
- before(:each) do
- @resource = Chef::Resource::Group.new("admin")
- end
-
- it "should create a new Chef::Resource::Group" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Group)
- end
+ let(:resource) { Chef::Resource::Group.new("admin") }
- it "should set the resource_name to :group" do
- expect(@resource.resource_name).to eql(:group)
+ it "sets the resource_name to :group" do
+ expect(resource.resource_name).to eql(:group)
end
- it "should set the group_name equal to the argument to initialize" do
- expect(@resource.group_name).to eql("admin")
+ it "sets the group_name equal to the argument to initialize" do
+ expect(resource.group_name).to eql("admin")
end
- it "should default gid to nil" do
- expect(@resource.gid).to eql(nil)
+ it "defaults gid to nil" do
+ expect(resource.gid).to eql(nil)
end
- it "should default members to an empty array" do
- expect(@resource.members).to eql([])
+ it "defaults members to an empty array" do
+ expect(resource.members).to eql([])
end
- it "should alias users to members, also an empty array" do
- expect(@resource.users).to eql([])
+ it "aliases users to members, also an empty array" do
+ expect(resource.users).to eql([])
end
- it "should set action to :create" do
- expect(@resource.action).to eql([:create])
+ it "sets action to :create" do
+ expect(resource.action).to eql([:create])
end
%w{create remove modify manage}.each do |action|
- it "should allow action #{action}" do
- expect(@resource.allowed_actions.detect { |a| a == action.to_sym }).to eql(action.to_sym)
+ it "allows action #{action}" do
+ expect(resource.allowed_actions.detect { |a| a == action.to_sym }).to eql(action.to_sym)
end
end
- it "should accept domain groups (@ or \ separator) on non-windows" do
- expect { @resource.group_name "domain\@group" }.not_to raise_error
- expect(@resource.group_name).to eq("domain\@group")
- expect { @resource.group_name "domain\\group" }.not_to raise_error
- expect(@resource.group_name).to eq("domain\\group")
- expect { @resource.group_name "domain\\group^name" }.not_to raise_error
- expect(@resource.group_name).to eq("domain\\group^name")
+ it "accepts domain groups (@ or \ separator) on non-windows" do
+ expect { resource.group_name "domain\@group" }.not_to raise_error
+ expect(resource.group_name).to eq("domain\@group")
+ expect { resource.group_name "domain\\group" }.not_to raise_error
+ expect(resource.group_name).to eq("domain\\group")
+ expect { resource.group_name "domain\\group^name" }.not_to raise_error
+ expect(resource.group_name).to eq("domain\\group^name")
end
end
describe Chef::Resource::Group, "group_name" do
- before(:each) do
- @resource = Chef::Resource::Group.new("admin")
- end
+ let(:resource) { Chef::Resource::Group.new("admin") }
- it "should allow a string" do
- @resource.group_name "pirates"
- expect(@resource.group_name).to eql("pirates")
+ it "allows a string" do
+ resource.group_name "pirates"
+ expect(resource.group_name).to eql("pirates")
end
- it "should not allow a hash" do
- expect { @resource.send(:group_name, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.send(:group_name, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
end
end
describe Chef::Resource::Group, "gid" do
- before(:each) do
- @resource = Chef::Resource::Group.new("admin")
- end
+ let(:resource) { Chef::Resource::Group.new("admin") }
- it "should allow an integer" do
- @resource.gid 100
- expect(@resource.gid).to eql(100)
+ it "allows an integer" do
+ resource.gid 100
+ expect(resource.gid).to eql(100)
end
- it "should not allow a hash" do
- expect { @resource.send(:gid, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.send(:gid, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
end
end
describe Chef::Resource::Group, "members" do
- before(:each) do
- @resource = Chef::Resource::Group.new("admin")
- end
+ let(:resource) { Chef::Resource::Group.new("admin") }
[ :users, :members].each do |method|
- it "(#{method}) should allow and convert a string" do
- @resource.send(method, "aj")
- expect(@resource.send(method)).to eql(["aj"])
+ it "(#{method}) allows and convert a string" do
+ resource.send(method, "aj")
+ expect(resource.send(method)).to eql(["aj"])
end
it "(#{method}) should split a string on commas" do
- @resource.send(method, "aj,adam")
- expect(@resource.send(method)).to eql( %w{aj adam} )
+ resource.send(method, "aj,adam")
+ expect(resource.send(method)).to eql( %w{aj adam} )
end
- it "(#{method}) should allow an array" do
- @resource.send(method, %w{aj adam})
- expect(@resource.send(method)).to eql( %w{aj adam} )
+ it "(#{method}) allows an array" do
+ resource.send(method, %w{aj adam})
+ expect(resource.send(method)).to eql( %w{aj adam} )
end
- it "(#{method}) should not allow a hash" do
- expect { @resource.send(method, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
+ it "(#{method}) does not allow a hash" do
+ expect { resource.send(method, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
end
end
end
describe Chef::Resource::Group, "append" do
- before(:each) do
- @resource = Chef::Resource::Group.new("admin")
- end
+ let(:resource) { Chef::Resource::Group.new("admin") }
- it "should default to false" do
- expect(@resource.append).to eql(false)
+ it "defaults to false" do
+ expect(resource.append).to eql(false)
end
- it "should allow a boolean" do
- @resource.append true
- expect(@resource.append).to eql(true)
+ it "allows a boolean" do
+ resource.append true
+ expect(resource.append).to eql(true)
end
- it "should not allow a hash" do
- expect { @resource.send(:gid, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.send(:gid, { :aj => "is freakin awesome" }) }.to raise_error(ArgumentError)
end
describe "when it has members" do
before do
- @resource.group_name("pokemon")
- @resource.members(%w{blastoise pikachu})
+ resource.group_name("pokemon")
+ resource.members(%w{blastoise pikachu})
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:members]).to eql(%w{blastoise pikachu})
end
it "returns the group name as its identity" do
- expect(@resource.identity).to eq("pokemon")
+ expect(resource.identity).to eq("pokemon")
end
end
end
diff --git a/spec/unit/resource/homebrew_package_spec.rb b/spec/unit/resource/homebrew_package_spec.rb
index cfcfcd9c3a..c3383a5abc 100644
--- a/spec/unit/resource/homebrew_package_spec.rb
+++ b/spec/unit/resource/homebrew_package_spec.rb
@@ -30,6 +30,10 @@ describe Chef::Resource::HomebrewPackage, "initialize" do
let(:resource) { Chef::Resource::HomebrewPackage.new("emacs") }
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
+ end
+
shared_examples "home_brew user set and returned" do
it "returns the configured homebrew_user" do
resource.homebrew_user user
diff --git a/spec/unit/resource/http_request_spec.rb b/spec/unit/resource/http_request_spec.rb
index 318a154b88..92c84962d7 100644
--- a/spec/unit/resource/http_request_spec.rb
+++ b/spec/unit/resource/http_request_spec.rb
@@ -20,39 +20,31 @@
require "spec_helper"
describe Chef::Resource::HttpRequest do
+ let(:resource) { Chef::Resource::HttpRequest.new("fakey_fakerton") }
- before(:each) do
- @resource = Chef::Resource::HttpRequest.new("fakey_fakerton")
+ it "sets url to a string" do
+ resource.url "http://slashdot.org"
+ expect(resource.url).to eql("http://slashdot.org")
end
- it "should create a new Chef::Resource::HttpRequest" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::HttpRequest)
+ it "sets the message to the name by default" do
+ expect(resource.message).to eql("fakey_fakerton")
end
- it "should set url to a string" do
- @resource.url "http://slashdot.org"
- expect(@resource.url).to eql("http://slashdot.org")
- end
-
- it "should set the message to the name by default" do
- expect(@resource.message).to eql("fakey_fakerton")
- end
-
- it "should set message to a string" do
- @resource.message "monkeybars"
- expect(@resource.message).to eql("monkeybars")
+ it "sets message to a string" do
+ resource.message "monkeybars"
+ expect(resource.message).to eql("monkeybars")
end
describe "when it has a message and headers" do
before do
- @resource.url("http://www.trololol.net")
- @resource.message("Get sum post brah.")
- @resource.headers({ "head" => "tail" })
+ resource.url("http://www.trololol.net")
+ resource.message("Get sum post brah.")
+ resource.headers({ "head" => "tail" })
end
it "returns the url as its identity" do
- expect(@resource.identity).to eq("http://www.trololol.net")
+ expect(resource.identity).to eq("http://www.trololol.net")
end
end
diff --git a/spec/unit/resource/ifconfig_spec.rb b/spec/unit/resource/ifconfig_spec.rb
index 699ebf1233..3221d0b864 100644
--- a/spec/unit/resource/ifconfig_spec.rb
+++ b/spec/unit/resource/ifconfig_spec.rb
@@ -55,7 +55,7 @@ describe Chef::Resource::Ifconfig do
@node.automatic_attrs[:platform_version] = version
end
- it "should use an ordinary Provider::Ifconfig as a provider for #{platform} #{version}" do
+ it "uses an ordinary Provider::Ifconfig as a provider for #{platform} #{version}" do
expect(@resource.provider_for_action(:add).class).to eq(Chef::Provider::Ifconfig)
end
end
@@ -68,7 +68,7 @@ describe Chef::Resource::Ifconfig do
@node.automatic_attrs[:platform_version] = version
end
- it "should use an Provider::Ifconfig::Redhat as a provider for #{platform} #{version}" do
+ it "uses an Provider::Ifconfig::Redhat as a provider for #{platform} #{version}" do
expect(@resource.provider_for_action(:add)).to be_a_kind_of(Chef::Provider::Ifconfig::Redhat)
end
end
@@ -81,7 +81,7 @@ describe Chef::Resource::Ifconfig do
@node.automatic_attrs[:platform_version] = version
end
- it "should use an Ifconfig::Debian as a provider for #{platform} #{version}" do
+ it "uses an Ifconfig::Debian as a provider for #{platform} #{version}" do
expect(@resource.provider_for_action(:add)).to be_a_kind_of(Chef::Provider::Ifconfig::Debian)
end
end
diff --git a/spec/unit/resource/ips_package_spec.rb b/spec/unit/resource/ips_package_spec.rb
index fd1fe2840c..b19f6bdf58 100644
--- a/spec/unit/resource/ips_package_spec.rb
+++ b/spec/unit/resource/ips_package_spec.rb
@@ -29,12 +29,14 @@ describe Chef::Resource::IpsPackage, "initialize" do
os: "solaris2"
)
- before(:each) do
- @resource = Chef::Resource::IpsPackage.new("crypto/gnupg")
+ let(:resource) { Chef::Resource::IpsPackage.new("crypto/gnupg") }
+
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
end
it "should support accept_license" do
- @resource.accept_license(true)
- expect(@resource.accept_license).to eql(true)
+ resource.accept_license(true)
+ expect(resource.accept_license).to eql(true)
end
end
diff --git a/spec/unit/resource/ksh_spec.rb b/spec/unit/resource/ksh_spec.rb
index 6c3ba291b4..7b651abacc 100644
--- a/spec/unit/resource/ksh_spec.rb
+++ b/spec/unit/resource/ksh_spec.rb
@@ -20,21 +20,18 @@ require "spec_helper"
describe Chef::Resource::Ksh do
- before(:each) do
- @resource = Chef::Resource::Ksh.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::Ksh.new("fakey_fakerton") }
- it "should create a new Chef::Resource::Ksh" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Ksh)
+ it "is a subclass of Chef::Resource::Script" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Script)
end
- it "should have a resource name of :ksh" do
- expect(@resource.resource_name).to eql(:ksh)
+ it "has a resource name of :ksh" do
+ expect(resource.resource_name).to eql(:ksh)
end
- it "should have an interpreter of ksh" do
- expect(@resource.interpreter).to eql("ksh")
+ it "has an interpreter of ksh" do
+ expect(resource.interpreter).to eql("ksh")
end
end
diff --git a/spec/unit/resource/launchd_spec.rb b/spec/unit/resource/launchd_spec.rb
index 98d21a8234..1fcfc25e3b 100644
--- a/spec/unit/resource/launchd_spec.rb
+++ b/spec/unit/resource/launchd_spec.rb
@@ -1,29 +1,31 @@
#
+# 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::Launchd do
- @launchd = Chef::Resource::Launchd.new("io.chef.chef-client")
- let(:resource) do
- Chef::Resource::Launchd.new(
- "io.chef.chef-client",
- run_context
- ) end
-
- it "should create a new Chef::Resource::Launchd" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::Launchd)
- end
+ let(:resource) { Chef::Resource::Launchd.new("io.chef.chef-client" ) }
- it "should have a resource name of Launchd" do
+ it "has a resource name of Launchd" do
expect(resource.resource_name).to eql(:launchd)
end
- it "should have a default action of create" do
+ it "has a default action of create" do
expect(resource.action).to eql([:create])
end
- it "should accept enable, disable, create, and delete as actions" do
+ it "accepts enable, disable, create, and delete as actions" do
expect { resource.action :enable }.not_to raise_error
expect { resource.action :disable }.not_to raise_error
expect { resource.action :create }.not_to raise_error
diff --git a/spec/unit/resource/link_spec.rb b/spec/unit/resource/link_spec.rb
index adfd0020f5..4f4f8c7c9f 100644
--- a/spec/unit/resource/link_spec.rb
+++ b/spec/unit/resource/link_spec.rb
@@ -20,115 +20,110 @@
require "spec_helper"
describe Chef::Resource::Link do
+ let(:resource) { Chef::Resource::Link.new("fakey_fakerton") }
before(:each) do
expect_any_instance_of(Chef::Resource::Link).to receive(:verify_links_supported!).and_return(true)
- @resource = Chef::Resource::Link.new("fakey_fakerton")
end
- it "should create a new Chef::Resource::Link" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Link)
+ it "has a name property" do
+ expect(resource.name).to eql("fakey_fakerton")
end
- it "should have a name" do
- expect(@resource.name).to eql("fakey_fakerton")
- end
-
- it "should have a default action of 'create'" do
- expect(@resource.action).to eql([:create])
+ it "has a default action of 'create'" do
+ expect(resource.action).to eql([:create])
end
{ :create => false, :delete => false, :blues => true }.each do |action, bad_value|
it "should #{bad_value ? 'not' : ''} accept #{action}" do
if bad_value
- expect { @resource.action action }.to raise_error(ArgumentError)
+ expect { resource.action action }.to raise_error(ArgumentError)
else
- expect { @resource.action action }.not_to raise_error
+ expect { resource.action action }.not_to raise_error
end
end
end
- it "should use the object name as the target_file by default" do
- expect(@resource.target_file).to eql("fakey_fakerton")
+ it "uses the object name as the target_file by default" do
+ expect(resource.target_file).to eql("fakey_fakerton")
end
- it "should accept a delayed evaluator as the target path" do
- @resource.target_file Chef::DelayedEvaluator.new { "my_lazy_name" }
- expect(@resource.target_file).to eql("my_lazy_name")
+ it "accepts a delayed evaluator as the target path" do
+ resource.target_file Chef::DelayedEvaluator.new { "my_lazy_name" }
+ expect(resource.target_file).to eql("my_lazy_name")
end
- it "should accept a delayed evaluator when accessing via 'path'" do
- @resource.target_file Chef::DelayedEvaluator.new { "my_lazy_name" }
- expect(@resource.path).to eql("my_lazy_name")
+ it "accepts a delayed evaluator when accessing via 'path'" do
+ resource.target_file Chef::DelayedEvaluator.new { "my_lazy_name" }
+ expect(resource.path).to eql("my_lazy_name")
end
- it "should accept a delayed evaluator via 'to'" do
- @resource.to Chef::DelayedEvaluator.new { "my_lazy_name" }
- expect(@resource.to).to eql("my_lazy_name")
+ it "accepts a delayed evaluator via 'to'" do
+ resource.to Chef::DelayedEvaluator.new { "my_lazy_name" }
+ expect(resource.to).to eql("my_lazy_name")
end
- it "should accept a string as the link source via 'to'" do
- expect { @resource.to "/tmp" }.not_to raise_error
+ it "accepts a string as the link source via 'to'" do
+ expect { resource.to "/tmp" }.not_to raise_error
end
- it "should not accept a Hash for the link source via 'to'" do
- expect { @resource.to Hash.new }.to raise_error(ArgumentError)
+ it "does not accept a Hash for the link source via 'to'" do
+ expect { resource.to Hash.new }.to raise_error(ArgumentError)
end
- it "should allow you to set a link source via 'to'" do
- @resource.to "/tmp/foo"
- expect(@resource.to).to eql("/tmp/foo")
+ it "allows you to set a link source via 'to'" do
+ resource.to "/tmp/foo"
+ expect(resource.to).to eql("/tmp/foo")
end
- it "should allow you to specify the link type" do
- @resource.link_type "symbolic"
- expect(@resource.link_type).to eql(:symbolic)
+ it "allows you to specify the link type" do
+ resource.link_type "symbolic"
+ expect(resource.link_type).to eql(:symbolic)
end
- it "should default to a symbolic link" do
- expect(@resource.link_type).to eql(:symbolic)
+ it "defaults to a symbolic link" do
+ expect(resource.link_type).to eql(:symbolic)
end
- it "should accept a hard link_type" do
- @resource.link_type :hard
- expect(@resource.link_type).to eql(:hard)
+ it "accepts a hard link_type" do
+ resource.link_type :hard
+ expect(resource.link_type).to eql(:hard)
end
- it "should reject any other link_type but :hard and :symbolic" do
- expect { @resource.link_type "x-men" }.to raise_error(ArgumentError)
+ it "rejects any other link_type but :hard and :symbolic" do
+ expect { resource.link_type "x-men" }.to raise_error(ArgumentError)
end
- it "should accept a group name or id for group" do
- expect { @resource.group "root" }.not_to raise_error
- expect { @resource.group 123 }.not_to raise_error
- expect { @resource.group "root:goo" }.to raise_error(ArgumentError)
+ it "accepts a group name or id for group" do
+ expect { resource.group "root" }.not_to raise_error
+ expect { resource.group 123 }.not_to raise_error
+ expect { resource.group "root:goo" }.to raise_error(ArgumentError)
end
- it "should accept a user name or id for owner" do
- expect { @resource.owner "root" }.not_to raise_error
- expect { @resource.owner 123 }.not_to raise_error
- expect { @resource.owner "root:goo" }.to raise_error(ArgumentError)
+ it "accepts a user name or id for owner" do
+ expect { resource.owner "root" }.not_to raise_error
+ expect { resource.owner 123 }.not_to raise_error
+ expect { resource.owner "root:goo" }.to raise_error(ArgumentError)
end
describe "when it has to, link_type, owner, and group" do
before do
- @resource.target_file("/var/target.tar")
- @resource.to("/to/dir/file.tar")
- @resource.link_type(:symbolic)
- @resource.owner("root")
- @resource.group("0664")
+ resource.target_file("/var/target.tar")
+ resource.to("/to/dir/file.tar")
+ resource.link_type(:symbolic)
+ resource.owner("root")
+ resource.group("0664")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:to]).to eq("/to/dir/file.tar")
expect(state[:owner]).to eq("root")
expect(state[:group]).to eq("0664")
end
it "returns the target file as its identity" do
- expect(@resource.identity).to eq("/var/target.tar")
+ expect(resource.identity).to eq("/var/target.tar")
end
end
end
diff --git a/spec/unit/resource/log_spec.rb b/spec/unit/resource/log_spec.rb
index 18a1eb65bf..9646b23b53 100644
--- a/spec/unit/resource/log_spec.rb
+++ b/spec/unit/resource/log_spec.rb
@@ -21,53 +21,44 @@ require "spec_helper"
describe Chef::Resource::Log do
- before(:each) do
- @log_str = "this is my string to log"
- @resource = Chef::Resource::Log.new(@log_str)
- end
-
- it "should create a new Chef::Resource::Log" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Log)
- end
+ let(:log_str) { "this is my string to log" }
+ let(:resource) { Chef::Resource::Log.new(log_str) }
it "supports the :write actions" do
- expect(@resource.allowed_actions).to include(:write)
+ expect(resource.allowed_actions).to include(:write)
end
- it "should have a name of log" do
- expect(@resource.resource_name).to eq(:log)
+ it "has a name of log" do
+ expect(resource.resource_name).to eq(:log)
end
- it "should allow you to set a log string" do
- expect(@resource.name).to eq(@log_str)
+ it "allows you to set a log string" do
+ expect(resource.name).to eq(log_str)
end
- it "should set the message to the first argument to new" do
- expect(@resource.message).to eq(@log_str)
+ it "sets the message to the first argument to new" do
+ expect(resource.message).to eq(log_str)
end
- it "should accept a string for the log message" do
- @resource.message "this is different"
- expect(@resource.message).to eq("this is different")
+ it "accepts a string for the log message" do
+ resource.message "this is different"
+ expect(resource.message).to eq("this is different")
end
- it "should accept a vaild level option" do
- @resource.level :debug
- @resource.level :info
- @resource.level :warn
- @resource.level :error
- @resource.level :fatal
- expect { @resource.level :unsupported }.to raise_error(ArgumentError)
+ it "accepts a vaild level option" do
+ resource.level :debug
+ resource.level :info
+ resource.level :warn
+ resource.level :error
+ resource.level :fatal
+ expect { resource.level :unsupported }.to raise_error(ArgumentError)
end
describe "when the identity is defined" do
- before do
- @resource = Chef::Resource::Log.new("ery day I'm loggin-in")
- end
+ let(:resource) { Chef::Resource::Log.new("ery day I'm loggin-in") }
it "returns the log string as its identity" do
- expect(@resource.identity).to eq("ery day I'm loggin-in")
+ expect(resource.identity).to eq("ery day I'm loggin-in")
end
end
end
diff --git a/spec/unit/resource/mdadm_spec.rb b/spec/unit/resource/mdadm_spec.rb
index f3cadbe499..6d595dc0f8 100644
--- a/spec/unit/resource/mdadm_spec.rb
+++ b/spec/unit/resource/mdadm_spec.rb
@@ -21,86 +21,79 @@ require "spec_helper"
describe Chef::Resource::Mdadm do
- before(:each) do
- @resource = Chef::Resource::Mdadm.new("fakey_fakerton")
- end
-
- it "should create a new Chef::Resource::Mdadm" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Mdadm)
- end
+ let(:resource) { Chef::Resource::Mdadm.new("fakey_fakerton") }
- it "should have a resource name of :mdadm" do
- expect(@resource.resource_name).to eql(:mdadm)
+ it "has a resource name of :mdadm" do
+ expect(resource.resource_name).to eql(:mdadm)
end
- it "should have a default action of create" do
- expect(@resource.action).to eql([:create])
+ it "has a default action of create" do
+ expect(resource.action).to eql([:create])
end
- it "should accept create, assemble, stop as actions" do
- expect { @resource.action :create }.not_to raise_error
- expect { @resource.action :assemble }.not_to raise_error
- expect { @resource.action :stop }.not_to raise_error
+ it "accepts create, assemble, stop as actions" do
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :assemble }.not_to raise_error
+ expect { resource.action :stop }.not_to raise_error
end
- it "should allow you to set the raid_device attribute" do
- @resource.raid_device "/dev/md3"
- expect(@resource.raid_device).to eql("/dev/md3")
+ it "allows you to set the raid_device attribute" do
+ resource.raid_device "/dev/md3"
+ expect(resource.raid_device).to eql("/dev/md3")
end
- it "should allow you to set the chunk attribute" do
- @resource.chunk 256
- expect(@resource.chunk).to eql(256)
+ it "allows you to set the chunk attribute" do
+ resource.chunk 256
+ expect(resource.chunk).to eql(256)
end
- it "should allow you to set the level attribute" do
- @resource.level 1
- expect(@resource.level).to eql(1)
+ it "allows you to set the level attribute" do
+ resource.level 1
+ expect(resource.level).to eql(1)
end
- it "should allow you to set the metadata attribute" do
- @resource.metadata "1.2"
- expect(@resource.metadata).to eql("1.2")
+ it "allows you to set the metadata attribute" do
+ resource.metadata "1.2"
+ expect(resource.metadata).to eql("1.2")
end
- it "should allow you to set the bitmap attribute" do
- @resource.bitmap "internal"
- expect(@resource.bitmap).to eql("internal")
+ it "allows you to set the bitmap attribute" do
+ resource.bitmap "internal"
+ expect(resource.bitmap).to eql("internal")
end
- it "should allow you to set the layout attribute" do
- @resource.layout "f2"
- expect(@resource.layout).to eql("f2")
+ it "allows you to set the layout attribute" do
+ resource.layout "f2"
+ expect(resource.layout).to eql("f2")
end
- it "should allow you to set the devices attribute" do
- @resource.devices ["/dev/sda", "/dev/sdb"]
- expect(@resource.devices).to eql(["/dev/sda", "/dev/sdb"])
+ it "allows you to set the devices attribute" do
+ resource.devices ["/dev/sda", "/dev/sdb"]
+ expect(resource.devices).to eql(["/dev/sda", "/dev/sdb"])
end
- it "should allow you to set the exists attribute" do
- @resource.exists true
- expect(@resource.exists).to eql(true)
+ it "allows you to set the exists attribute" do
+ resource.exists true
+ expect(resource.exists).to eql(true)
end
describe "when it has devices, level, and chunk" do
before do
- @resource.raid_device("raider")
- @resource.devices(%w{device1 device2})
- @resource.level(1)
- @resource.chunk(42)
+ resource.raid_device("raider")
+ resource.devices(%w{device1 device2})
+ resource.level(1)
+ resource.chunk(42)
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:devices]).to eql(%w{device1 device2})
expect(state[:level]).to eq(1)
expect(state[:chunk]).to eq(42)
end
it "returns the raid device as its identity" do
- expect(@resource.identity).to eq("raider")
+ expect(resource.identity).to eq("raider")
end
end
diff --git a/spec/unit/resource/mount_spec.rb b/spec/unit/resource/mount_spec.rb
index 466b6ac8c0..41eb9c221f 100644
--- a/spec/unit/resource/mount_spec.rb
+++ b/spec/unit/resource/mount_spec.rb
@@ -20,192 +20,185 @@
require "spec_helper"
describe Chef::Resource::Mount do
- before(:each) do
- @resource = Chef::Resource::Mount.new("filesystem")
- end
-
- it "should create a new Chef::Resource::Mount" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Mount)
- end
+ let(:resource) { Chef::Resource::Mount.new("filesystem") }
- it "should have a name" do
- expect(@resource.name).to eql("filesystem")
+ it "has a name property" do
+ expect(resource.name).to eql("filesystem")
end
- it "should set mount_point to the name" do
- expect(@resource.mount_point).to eql("filesystem")
+ it "sets mount_point to the name" do
+ expect(resource.mount_point).to eql("filesystem")
end
- it "should have a default action of mount" do
- expect(@resource.action).to eql([:mount])
+ it "has a default action of mount" do
+ expect(resource.action).to eql([:mount])
end
- 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)
+ it "accepts 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
- it "should allow you to set the device attribute" do
- @resource.device "/dev/sdb3"
- expect(@resource.device).to eql("/dev/sdb3")
+ it "allows you to set the device attribute" do
+ resource.device "/dev/sdb3"
+ expect(resource.device).to eql("/dev/sdb3")
end
- it "should set fsck_device to '-' by default" do
- expect(@resource.fsck_device).to eql("-")
+ it "sets fsck_device to '-' by default" do
+ expect(resource.fsck_device).to eql("-")
end
- it "should allow you to set the fsck_device attribute" do
- @resource.fsck_device "/dev/rdsk/sdb3"
- expect(@resource.fsck_device).to eql("/dev/rdsk/sdb3")
+ it "allows you to set the fsck_device attribute" do
+ resource.fsck_device "/dev/rdsk/sdb3"
+ expect(resource.fsck_device).to eql("/dev/rdsk/sdb3")
end
- it "should allow you to set the fstype attribute" do
- @resource.fstype "nfs"
- expect(@resource.fstype).to eql("nfs")
+ it "allows you to set the fstype attribute" do
+ resource.fstype "nfs"
+ expect(resource.fstype).to eql("nfs")
end
- it "should allow you to set the dump attribute" do
- @resource.dump 1
- expect(@resource.dump).to eql(1)
+ it "allows you to set the dump attribute" do
+ resource.dump 1
+ expect(resource.dump).to eql(1)
end
- it "should allow you to set the pass attribute" do
- @resource.pass 1
- expect(@resource.pass).to eql(1)
+ it "allows you to set the pass attribute" do
+ resource.pass 1
+ expect(resource.pass).to eql(1)
end
- it "should set the options attribute to defaults" do
- expect(@resource.options).to eql(["defaults"])
+ it "sets the options attribute to defaults" do
+ expect(resource.options).to eql(["defaults"])
end
- it "should allow options to be sent as a string, and convert to array" do
- @resource.options "rw,noexec"
- expect(@resource.options).to be_a_kind_of(Array)
+ it "allows options to be sent as a string, and convert to array" do
+ resource.options "rw,noexec"
+ expect(resource.options).to be_a_kind_of(Array)
end
- it "should allow options attribute as an array" do
- @resource.options %w{ro nosuid}
- expect(@resource.options).to be_a_kind_of(Array)
+ it "allows options attribute as an array" do
+ resource.options %w{ro nosuid}
+ expect(resource.options).to be_a_kind_of(Array)
end
- it "should allow options to be sent as a delayed evaluator" do
- @resource.options Chef::DelayedEvaluator.new { %w{rw noexec} }
- expect(@resource.options).to eql(%w{rw noexec})
+ it "allows options to be sent as a delayed evaluator" do
+ resource.options Chef::DelayedEvaluator.new { %w{rw noexec} }
+ expect(resource.options).to eql(%w{rw noexec})
end
- it "should allow options to be sent as a delayed evaluator, and convert to array" do
- @resource.options Chef::DelayedEvaluator.new { "rw,noexec" }
- expect(@resource.options).to be_a_kind_of(Array)
- expect(@resource.options).to eql(%w{rw noexec})
+ it "allows options to be sent as a delayed evaluator, and convert to array" do
+ resource.options Chef::DelayedEvaluator.new { "rw,noexec" }
+ expect(resource.options).to be_a_kind_of(Array)
+ expect(resource.options).to eql(%w{rw noexec})
end
- it "should accept true for mounted" do
- @resource.mounted(true)
- expect(@resource.mounted).to eql(true)
+ it "accepts true for mounted" do
+ resource.mounted(true)
+ expect(resource.mounted).to eql(true)
end
- it "should accept false for mounted" do
- @resource.mounted(false)
- expect(@resource.mounted).to eql(false)
+ it "accepts false for mounted" do
+ resource.mounted(false)
+ expect(resource.mounted).to eql(false)
end
- it "should set mounted to false by default" do
- expect(@resource.mounted).to eql(false)
+ it "sets mounted to false by default" do
+ expect(resource.mounted).to eql(false)
end
- it "should not accept a string for mounted" do
- expect { @resource.mounted("poop") }.to raise_error(ArgumentError)
+ it "does not accept a string for mounted" do
+ expect { resource.mounted("poop") }.to raise_error(ArgumentError)
end
- it "should accept true for enabled" do
- @resource.enabled(true)
- expect(@resource.enabled).to eql(true)
+ it "accepts true for enabled" do
+ resource.enabled(true)
+ expect(resource.enabled).to eql(true)
end
- it "should accept false for enabled" do
- @resource.enabled(false)
- expect(@resource.enabled).to eql(false)
+ it "accepts false for enabled" do
+ resource.enabled(false)
+ expect(resource.enabled).to eql(false)
end
- it "should set enabled to false by default" do
- expect(@resource.enabled).to eql(false)
+ it "sets enabled to false by default" do
+ expect(resource.enabled).to eql(false)
end
- it "should not accept a string for enabled" do
- expect { @resource.enabled("poop") }.to raise_error(ArgumentError)
+ it "does not accept a string for enabled" do
+ expect { resource.enabled("poop") }.to raise_error(ArgumentError)
end
- it "should default all feature support to false" do
+ it "defaults all feature support to false" do
support_hash = { :remount => false }
- expect(@resource.supports).to eq(support_hash)
+ expect(resource.supports).to eq(support_hash)
end
- it "should allow you to set feature support as an array" do
+ it "allows you to set feature support as an array" do
support_array = [ :remount ]
support_hash = { :remount => true }
- @resource.supports(support_array)
- expect(@resource.supports).to eq(support_hash)
+ resource.supports(support_array)
+ expect(resource.supports).to eq(support_hash)
end
- it "should allow you to set feature support as a hash" do
+ it "allows you to set feature support as a hash" do
support_hash = { :remount => true }
- @resource.supports(support_hash)
- expect(@resource.supports).to eq(support_hash)
+ resource.supports(support_hash)
+ expect(resource.supports).to eq(support_hash)
end
- it "should allow you to set username" do
- @resource.username("Administrator")
- expect(@resource.username).to eq("Administrator")
+ it "allows you to set username" do
+ resource.username("Administrator")
+ expect(resource.username).to eq("Administrator")
end
- it "should allow you to set password" do
- @resource.password("Jetstream123!")
- expect(@resource.password).to eq("Jetstream123!")
+ it "allows you to set password" do
+ resource.password("Jetstream123!")
+ expect(resource.password).to eq("Jetstream123!")
end
- it "should allow you to set domain" do
- @resource.domain("TEST_DOMAIN")
- expect(@resource.domain).to eq("TEST_DOMAIN")
+ it "allows you to set domain" do
+ resource.domain("TEST_DOMAIN")
+ expect(resource.domain).to eq("TEST_DOMAIN")
end
describe "when it has mount point, device type, and fstype" do
before do
- @resource.device("charmander")
- @resource.mount_point("123.456")
- @resource.device_type(:device)
- @resource.fstype("ranked")
+ resource.device("charmander")
+ resource.mount_point("123.456")
+ resource.device_type(:device)
+ resource.fstype("ranked")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:mount_point]).to eq("123.456")
expect(state[:device_type]).to eql(:device)
expect(state[:fstype]).to eq("ranked")
end
it "returns the device as its identity" do
- expect(@resource.identity).to eq("charmander")
+ expect(resource.identity).to eq("charmander")
end
end
describe "when it has username, password and domain" do
before do
- @resource.mount_point("T:")
- @resource.device("charmander")
- @resource.username("Administrator")
- @resource.password("Jetstream123!")
- @resource.domain("TEST_DOMAIN")
+ resource.mount_point("T:")
+ resource.device("charmander")
+ resource.username("Administrator")
+ resource.password("Jetstream123!")
+ resource.domain("TEST_DOMAIN")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:mount_point]).to eq("T:")
expect(state[:username]).to eq("Administrator")
- expect(state[:password]).to eq("Jetstream123!")
+ expect(state[:password]).to eq("*sensitive value suppressed*")
expect(state[:domain]).to eq("TEST_DOMAIN")
expect(state[:device_type]).to eql(:device)
expect(state[:fstype]).to eq("auto")
diff --git a/spec/unit/resource/msu_package_spec.rb b/spec/unit/resource/msu_package_spec.rb
index 349a382b31..bc2529df9c 100644
--- a/spec/unit/resource/msu_package_spec.rb
+++ b/spec/unit/resource/msu_package_spec.rb
@@ -21,29 +21,33 @@ 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)
+ it "is a subclass of Chef::Resource::Package" do
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")
+ it "sets the default action as :install" do
+ expect(resource.action).to eql([:install])
end
- it "sets the default action as :install" do
- expect(resource.action).to eql(:install)
+ it "coerces name property to package_name property" do
+ expect(resource.package_name).to eql("test_pkg")
end
- it "raises error if invalid action is given" do
- expect { resource.action "abc" }.to raise_error(Chef::Exceptions::ValidationFailed)
+ it "coerces name property to a source property if source not provided" do
+ expect(resource.source).to end_with("test_pkg")
end
- it "coerce its name to a package_name" do
- expect(resource.package_name).to eql("test_pkg")
+ it "coerces name property to a source property if source not provided and package_name is" do
+ resource.package_name("package.msu")
+ expect(resource.source).to end_with("package.msu")
+ end
+
+ it "coerces source property if it does not looks like a path" do
+ resource.source("package.msu")
+ expect(resource.source).not_to eq("package.msu")
end
end
diff --git a/spec/unit/resource/ohai_spec.rb b/spec/unit/resource/ohai_spec.rb
index 574c09eeba..eb569aa3b7 100644
--- a/spec/unit/resource/ohai_spec.rb
+++ b/spec/unit/resource/ohai_spec.rb
@@ -20,41 +20,34 @@ require "spec_helper"
describe Chef::Resource::Ohai do
- before(:each) do
- @resource = Chef::Resource::Ohai.new("ohai_reload")
- end
-
- it "should create a new Chef::Resource::Ohai" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Ohai)
- end
+ let(:resource) { Chef::Resource::Ohai.new("ohai_reload") }
- it "should have a resource name of :ohai" do
- expect(@resource.resource_name).to eql(:ohai)
+ it "has a resource name of :ohai" do
+ expect(resource.resource_name).to eql(:ohai)
end
- it "should have a default action of reload" do
- expect(@resource.action).to eql([:reload])
+ it "has a default action of reload" do
+ expect(resource.action).to eql([:reload])
end
- it "should allow you to set the plugin attribute" do
- @resource.plugin "passwd"
- expect(@resource.plugin).to eql("passwd")
+ it "allows you to set the plugin attribute" do
+ resource.plugin "passwd"
+ expect(resource.plugin).to eql("passwd")
end
describe "when it has a plugin value" do
before do
- @resource.name("test")
- @resource.plugin("passwd")
+ resource.name("test")
+ resource.plugin("passwd")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:plugin]).to eq("passwd")
end
it "returns the name as its identity" do
- expect(@resource.identity).to eq("test")
+ expect(resource.identity).to eq("test")
end
end
diff --git a/spec/unit/resource/openbsd_package_spec.rb b/spec/unit/resource/openbsd_package_spec.rb
index 9bdc823576..17dc9f09ff 100644
--- a/spec/unit/resource/openbsd_package_spec.rb
+++ b/spec/unit/resource/openbsd_package_spec.rb
@@ -20,28 +20,24 @@
#
require "spec_helper"
-require "ostruct"
describe Chef::Resource::OpenbsdPackage do
-
- before(:each) do
- @node = Chef::Node.new
- @events = Chef::EventDispatch::Dispatcher.new
- @run_context = Chef::RunContext.new(@node, {}, @events)
- @resource = Chef::Resource::OpenbsdPackage.new("foo", @run_context)
- end
+ let(:node) { Chef::Node.new }
+ let(:events) { Chef::EventDispatch::Dispatcher.new }
+ let(:run_context) { Chef::RunContext.new(node, {}, events) }
+ let(:resource) { Chef::Resource::OpenbsdPackage.new("foo", run_context) }
describe "Initialization" do
- it "should return a Chef::Resource::OpenbsdPackage" do
- expect(@resource).to be_a_kind_of(Chef::Resource::OpenbsdPackage)
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
end
- it "should set the resource_name to :openbsd_package" do
- expect(@resource.resource_name).to eql(:openbsd_package)
+ it "sets the resource_name to :openbsd_package" do
+ expect(resource.resource_name).to eql(:openbsd_package)
end
- it "should not set the provider" do
- expect(@resource.provider).to be_nil
+ it "does not set the provider" do
+ expect(resource.provider).to be_nil
end
end
diff --git a/spec/unit/resource/openssl_dhparam.rb b/spec/unit/resource/openssl_dhparam.rb
new file mode 100644
index 0000000000..d1021d4f7e
--- /dev/null
+++ b/spec/unit/resource/openssl_dhparam.rb
@@ -0,0 +1,51 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::OpensslDhparam do
+
+ let(:resource) { Chef::Resource::OpensslDhparam.new("dhparam") }
+
+ it "has a resource name of :openssl_dhparam" do
+ expect(resource.resource_name).to eql(:openssl_dhparam)
+ end
+
+ it "has a default action of create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "has a default mode of '0640'" do
+ expect(resource.mode).to eql("0640")
+ end
+
+ it "has a default generator of 2" do
+ expect(resource.generator).to eql(2)
+ end
+
+ it "has a default key_length of 2048" do
+ expect(resource.key_length).to eql(2048)
+ end
+
+ it "only accepts valid key length" do
+ expect { resource.key_length 1234 }.to raise_error(ArgumentError)
+ end
+
+ it "the path property is the name property" do
+ expect(resource.path).to eql("dhparam")
+ end
+end
diff --git a/spec/unit/resource/openssl_rsa_private_key.rb b/spec/unit/resource/openssl_rsa_private_key.rb
new file mode 100644
index 0000000000..67bebf17fe
--- /dev/null
+++ b/spec/unit/resource/openssl_rsa_private_key.rb
@@ -0,0 +1,59 @@
+#
+# Copyright:: Copyright 2018, Chef Software, Inc.
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require "spec_helper"
+
+describe Chef::Resource::OpensslRsaPrivateKey do
+
+ let(:resource) { Chef::Resource::OpensslRsaPrivateKey.new("key") }
+
+ it "has a resource name of :openssl_rsa_private_key" do
+ expect(resource.resource_name).to eql(:openssl_rsa_private_key)
+ end
+
+ it "has a default action of create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "has a default mode of '0600'" do
+ expect(resource.mode).to eql("0600")
+ end
+
+ it "has a default key_cipher of 'des3'" do
+ expect(resource.key_cipher).to eql("des3")
+ end
+
+ it "only accepts valid key_cipher values" do
+ expect { resource.key_cipher "fako" }.to raise_error(ArgumentError)
+ end
+
+ it "has a default key_length of 2048" do
+ expect(resource.key_length).to eql(2048)
+ end
+
+ it "only accepts valid key length" do
+ expect { resource.key_length 1234 }.to raise_error(ArgumentError)
+ end
+
+ it "has a default force value of of false" do
+ expect(resource.force).to eql(false)
+ end
+
+ it "the path property is the name property" do
+ expect(resource.path).to eql("key")
+ end
+end
diff --git a/spec/unit/resource/timestamped_deploy_spec.rb b/spec/unit/resource/openssl_rsa_public_key.rb
index 5a2dc8ae02..d624e10338 100644
--- a/spec/unit/resource/timestamped_deploy_spec.rb
+++ b/spec/unit/resource/openssl_rsa_public_key.rb
@@ -1,6 +1,5 @@
#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright 2009-2016, Daniel DeLeo
+# Copyright:: Copyright 2018, Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,15 +17,23 @@
require "spec_helper"
-describe Chef::Resource::TimestampedDeploy, "initialize" do
+describe Chef::Resource::OpensslRsaPublicKey do
- static_provider_resolution(
- resource: Chef::Resource::TimestampedDeploy,
- provider: Chef::Provider::Deploy::Timestamped,
- name: :timestamped_deploy,
- action: :deploy,
- os: "linux",
- platform_family: "rhel"
- )
+ let(:resource) { Chef::Resource::OpensslRsaPublicKey.new("key") }
+ it "has a resource name of :openssl_rsa_public_key" do
+ expect(resource.resource_name).to eql(:openssl_rsa_public_key)
+ end
+
+ it "has a default action of create" do
+ expect(resource.action).to eql([:create])
+ end
+
+ it "has a default mode of '0640'" do
+ expect(resource.mode).to eql("0640")
+ end
+
+ it "the path property is the name property" do
+ expect(resource.path).to eql("key")
+ end
end
diff --git a/spec/unit/resource/osx_profile_spec.rb b/spec/unit/resource/osx_profile_spec.rb
index 513e570e7c..291b205466 100644
--- a/spec/unit/resource/osx_profile_spec.rb
+++ b/spec/unit/resource/osx_profile_spec.rb
@@ -25,36 +25,31 @@ describe Chef::Resource::OsxProfile do
run_context)
end
- it "should create a new Chef::Resource::OsxProfile" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::OsxProfile)
- end
-
- it "should have a resource name of profile" do
+ it "has a resource name of profile" do
expect(resource.resource_name).to eql(:osx_profile)
end
- it "should have a default action of install" do
+ it "has a default action of install" do
expect(resource.action).to eql([:install])
end
- it "should accept install and remove as actions" do
+ it "accepts install and remove as actions" do
expect { resource.action :install }.not_to raise_error
expect { resource.action :remove }.not_to raise_error
end
- it "should allow you to set the profile attribute" do
+ it "allows you to set the profile attribute" do
resource.profile "com.testprofile.screensaver"
expect(resource.profile).to eql("com.testprofile.screensaver")
end
- it "should allow you to set the profile attribute to a string" do
+ it "allows you to set the profile attribute to a string" do
resource.profile "com.testprofile.screensaver"
expect(resource.profile).to be_a(String)
expect(resource.profile).to eql("com.testprofile.screensaver")
end
- it "should allow you to set the profile attribute to a hash" do
+ it "allows you to set the profile attribute to a hash" do
test_profile = { "profile" => false }
resource.profile test_profile
expect(resource.profile).to be_a(Hash)
diff --git a/spec/unit/resource/package_spec.rb b/spec/unit/resource/package_spec.rb
index 84f92f26b5..38d0bfce96 100644
--- a/spec/unit/resource/package_spec.rb
+++ b/spec/unit/resource/package_spec.rb
@@ -20,84 +20,75 @@
require "spec_helper"
describe Chef::Resource::Package do
+ let(:resource) { Chef::Resource::Package.new("emacs") }
- before(:each) do
- @resource = Chef::Resource::Package.new("emacs")
+ it "sets the package_name to the first argument to new" do
+ expect(resource.package_name).to eql("emacs")
end
- it "should create a new Chef::Resource::Package" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Package)
+ it "accepts a string for the package name" do
+ resource.package_name "something"
+ expect(resource.package_name).to eql("something")
end
- it "should set the package_name to the first argument to new" do
- expect(@resource.package_name).to eql("emacs")
+ it "accepts a string for the version" do
+ resource.version "something"
+ expect(resource.version).to eql("something")
end
- it "should accept a string for the package name" do
- @resource.package_name "something"
- expect(@resource.package_name).to eql("something")
+ it "accepts a string for the response file" do
+ resource.response_file "something"
+ expect(resource.response_file).to eql("something")
end
- it "should accept a string for the version" do
- @resource.version "something"
- expect(@resource.version).to eql("something")
+ it "accepts a hash for response file template variables" do
+ resource.response_file_variables({ :variables => true })
+ expect(resource.response_file_variables).to eql({ :variables => true })
end
- it "should accept a string for the response file" do
- @resource.response_file "something"
- expect(@resource.response_file).to eql("something")
+ it "accepts a string for the source" do
+ resource.source "something"
+ expect(resource.source).to eql("something")
end
- it "should accept a hash for response file template variables" do
- @resource.response_file_variables({ :variables => true })
- expect(@resource.response_file_variables).to eql({ :variables => true })
+ it "accepts a string for the options" do
+ resource.options "something"
+ expect(resource.options).to eql(["something"])
end
- it "should accept a string for the source" do
- @resource.source "something"
- expect(@resource.source).to eql("something")
- end
-
- it "should accept a string for the options" do
- @resource.options "something"
- expect(@resource.options).to eql(["something"])
- end
-
- it "should split options" do
- @resource.options "-a -b 'arg with spaces' -b \"and quotes\""
- expect(@resource.options).to eql(["-a", "-b", "arg with spaces", "-b", "and quotes"])
+ it "splits options" do
+ resource.options "-a -b 'arg with spaces' -b \"and quotes\""
+ expect(resource.options).to eql(["-a", "-b", "arg with spaces", "-b", "and quotes"])
end
describe "when it has a package_name and version" do
before do
- @resource.package_name("tomcat")
- @resource.version("10.9.8")
- @resource.options("-al")
+ resource.package_name("tomcat")
+ resource.version("10.9.8")
+ resource.options("-al")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:version]).to eq("10.9.8")
expect(state[:options]).to eq(["-al"])
end
it "returns the file path as its identity" do
- expect(@resource.identity).to eq("tomcat")
+ 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" ])
+ resource.options [ "-a", "-l" ]
+ expect(resource.options).to eq(["-a", "-l" ])
end
end
# String, Integer
[ "600", 600 ].each do |val|
it "supports setting a timeout as a #{val.class}" do
- @resource.timeout(val)
- expect(@resource.timeout).to eql(val)
+ resource.timeout(val)
+ expect(resource.timeout).to eql(val)
end
end
-
end
diff --git a/spec/unit/resource/perl_spec.rb b/spec/unit/resource/perl_spec.rb
index 417d74a8c2..f8e11c465c 100644
--- a/spec/unit/resource/perl_spec.rb
+++ b/spec/unit/resource/perl_spec.rb
@@ -20,21 +20,17 @@ require "spec_helper"
describe Chef::Resource::Perl do
- before(:each) do
- @resource = Chef::Resource::Perl.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::Perl.new("fakey_fakerton") }
- it "should create a new Chef::Resource::Perl" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Perl)
+ it "is a subclass of Chef::Resource::Script" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Script)
end
- it "should have a resource name of :perl" do
- expect(@resource.resource_name).to eql(:perl)
+ it "has a resource name of :perl" do
+ expect(resource.resource_name).to eql(:perl)
end
- it "should have an interpreter of perl" do
- expect(@resource.interpreter).to eql("perl")
+ it "has an interpreter of perl" do
+ expect(resource.interpreter).to eql("perl")
end
-
end
diff --git a/spec/unit/resource/portage_package_spec.rb b/spec/unit/resource/portage_package_spec.rb
index d2336744bf..02a7aef39a 100644
--- a/spec/unit/resource/portage_package_spec.rb
+++ b/spec/unit/resource/portage_package_spec.rb
@@ -16,23 +16,21 @@
# limitations under the License.
#
-require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
+require "spec_helper"
describe Chef::Resource::PortagePackage, "initialize" do
- before(:each) do
- @resource = Chef::Resource::PortagePackage.new("foo")
- end
+ let(:resource) { Chef::Resource::PortagePackage.new("foo") }
- it "should return a Chef::Resource::PortagePackage" do
- expect(@resource).to be_a_kind_of(Chef::Resource::PortagePackage)
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
end
- it "should set the resource_name to :portage_package" do
- expect(@resource.resource_name).to eql(:portage_package)
+ it "sets the resource_name to :portage_package" do
+ expect(resource.resource_name).to eql(:portage_package)
end
- it "should set the provider to Chef::Provider::Package::Portage" do
- expect(@resource.provider).to eql(Chef::Provider::Package::Portage)
+ it "sets the provider to Chef::Provider::Package::Portage" do
+ expect(resource.provider).to eql(Chef::Provider::Package::Portage)
end
end
diff --git a/spec/unit/resource/powershell_package_spec.rb b/spec/unit/resource/powershell_package_spec.rb
index ff4aa991a7..701014bd95 100644
--- a/spec/unit/resource/powershell_package_spec.rb
+++ b/spec/unit/resource/powershell_package_spec.rb
@@ -22,46 +22,44 @@ 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)
+ it "is a subclass of Chef::Resource::Package" do
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
+ it "has a resource name of :powershell_package" do
expect(resource.resource_name).to eql(:powershell_package)
end
- it "should coerce its name to a package_name array" do
+ it "coerces 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
+ it "the package_name setter coerces to arrays" do
resource.package_name("git")
expect(resource.package_name).to eql(["git"])
end
- it "the package_name setter should accept arrays" do
+ it "the package_name setter accepts 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
+ it "the name accepts 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
+ it "the default version is nil" do
expect(resource.version).to eql(nil)
end
- it "the version setter should coerce to arrays" do
+ it "the version setter coerces 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
+ it "the version setter accepts arrays" do
resource.version(["1.2.3", "4.5.6"])
expect(resource.version).to eql(["1.2.3", "4.5.6"])
end
diff --git a/spec/unit/resource/python_spec.rb b/spec/unit/resource/python_spec.rb
index aba84c4000..5a4dc8eca8 100644
--- a/spec/unit/resource/python_spec.rb
+++ b/spec/unit/resource/python_spec.rb
@@ -20,21 +20,13 @@ require "spec_helper"
describe Chef::Resource::Python do
- before(:each) do
- @resource = Chef::Resource::Python.new("fakey_fakerton")
- end
-
- it "should create a new Chef::Resource::Python" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Python)
- end
+ let(:resource) { Chef::Resource::Python.new("fakey_fakerton") }
- it "should have a resource name of :python" do
- expect(@resource.resource_name).to eql(:python)
+ it "has a resource name of :python" do
+ expect(resource.resource_name).to eql(:python)
end
- it "should have an interpreter of python" do
- expect(@resource.interpreter).to eql("python")
+ it "has an interpreter of python" do
+ expect(resource.interpreter).to eql("python")
end
-
end
diff --git a/spec/unit/resource/reboot_spec.rb b/spec/unit/resource/reboot_spec.rb
new file mode 100644
index 0000000000..adcfb9e6a4
--- /dev/null
+++ b/spec/unit/resource/reboot_spec.rb
@@ -0,0 +1,45 @@
+#
+# 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::Resource::Reboot do
+
+ let(:resource) { Chef::Resource::Reboot.new("reboot me!") }
+
+ it "has a default action of :nothing" do
+ expect(resource.action).to eql([:nothing])
+ end
+
+ it "supports the :nothing, :request_reboot, :reboot_now, and :cancel actions" do
+ expect(resource.allowed_actions).to include(:nothing, :request_reboot, :reboot_now, :cancel)
+ end
+
+ it "has a resource_name of :reboot" do
+ expect(resource.resource_name).to eq(:reboot)
+ end
+
+ it "accepts a String for the reboot reason" do
+ resource.reason "reasons"
+ expect(resource.reason).to eq("reasons")
+ end
+
+ it "accepts an Integer for delay_mins" do
+ resource.delay_mins 100
+ expect { resource.delay_mins "100" }.to raise_error(ArgumentError)
+ end
+end
diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb
index 067f2da36a..07ad4f820b 100644
--- a/spec/unit/resource/registry_key_spec.rb
+++ b/spec/unit/resource/registry_key_spec.rb
@@ -19,197 +19,178 @@
require "spec_helper"
describe Chef::Resource::RegistryKey, "initialize" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
-
- it "should create a new Chef::Resource::RegistryKey" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::RegistryKey)
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
- it "should set the resource_name to :registry_key" do
- expect(@resource.resource_name).to eql(:registry_key)
+ it "sets the resource_name to :registry_key" do
+ expect(resource.resource_name).to eql(:registry_key)
end
- it "should set the key equal to the argument to initialize" do
- expect(@resource.key).to eql('HKCU\Software\Raxicoricofallapatorius')
+ it "sets the key equal to the argument to initialize" do
+ expect(resource.key).to eql('HKCU\Software\Raxicoricofallapatorius')
end
- it "should default recursive to false" do
- expect(@resource.recursive).to eql(false)
+ it "defaults recursive to false" do
+ expect(resource.recursive).to eql(false)
end
- it "should default architecture to :machine" do
- expect(@resource.architecture).to eql(:machine)
+ it "defaults architecture to :machine" do
+ expect(resource.architecture).to eql(:machine)
end
- it "should set action to :create" do
- expect(@resource.action).to eql([:create])
+ it "sets action to :create" do
+ expect(resource.action).to eql([:create])
end
%w{create create_if_missing delete delete_key}.each do |action|
- it "should allow action #{action}" do
- expect(@resource.allowed_actions.detect { |a| a == action.to_sym }).to eql(action.to_sym)
+ it "allows action #{action}" do
+ expect(resource.allowed_actions.detect { |a| a == action.to_sym }).to eql(action.to_sym)
end
end
end
describe Chef::Resource::RegistryKey, "key" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
- it "should allow a string" do
- @resource.key 'HKCU\Software\Poosh'
- expect(@resource.key).to eql('HKCU\Software\Poosh')
+ it "allows a string" do
+ resource.key 'HKCU\Software\Poosh'
+ expect(resource.key).to eql('HKCU\Software\Poosh')
end
- it "should not allow an integer" do
- expect { @resource.send(:key, 100) }.to raise_error(ArgumentError)
+ it "does not allow an integer" do
+ expect { resource.send(:key, 100) }.to raise_error(ArgumentError)
end
- it "should not allow a hash" do
- expect { @resource.send(:key, { :sonic => "screwdriver" }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.send(:key, { :sonic => "screwdriver" }) }.to raise_error(ArgumentError)
end
end
describe Chef::Resource::RegistryKey, "values" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
- it "should allow a single proper hash of registry values" do
- @resource.values( { :name => "poosh", :type => :string, :data => "carmen" } )
- expect(@resource.values).to eql([ { :name => "poosh", :type => :string, :data => "carmen" } ])
+ it "allows a single proper hash of registry values" do
+ resource.values( { :name => "poosh", :type => :string, :data => "carmen" } )
+ expect(resource.values).to eql([ { :name => "poosh", :type => :string, :data => "carmen" } ])
end
- it "should allow an array of proper hashes of registry values" do
- @resource.values [ { :name => "poosh", :type => :string, :data => "carmen" } ]
- expect(@resource.values).to eql([ { :name => "poosh", :type => :string, :data => "carmen" } ])
+ it "allows an array of proper hashes of registry values" do
+ resource.values [ { :name => "poosh", :type => :string, :data => "carmen" } ]
+ expect(resource.values).to eql([ { :name => "poosh", :type => :string, :data => "carmen" } ])
end
- it "should return checksummed data if the type is unsafe" do
- @resource.values( { :name => "poosh", :type => :binary, :data => 255.chr * 1 })
- expect(@resource.values).to eql([ { :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" } ])
+ it "returns checksummed data if the type is unsafe" do
+ resource.values( { :name => "poosh", :type => :binary, :data => 255.chr * 1 })
+ expect(resource.values).to eql([ { :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" } ])
end
- it "should raise an exception if the name field is missing" do
- expect { @resource.values [ { :type => :string, :data => "carmen" } ] }.to raise_error(ArgumentError)
+ it "raises an exception if the name field is missing" do
+ expect { resource.values [ { :type => :string, :data => "carmen" } ] }.to raise_error(ArgumentError)
end
- it "should raise an exception if extra fields are present" do
- expect { @resource.values [ { :name => "poosh", :type => :string, :data => "carmen", :screwdriver => "sonic" } ] }.to raise_error(ArgumentError)
+ it "raises an exception if extra fields are present" do
+ expect { resource.values [ { :name => "poosh", :type => :string, :data => "carmen", :screwdriver => "sonic" } ] }.to raise_error(ArgumentError)
end
- it "should not allow a string" do
- expect { @resource.send(:values, "souffle") }.to raise_error(ArgumentError)
+ it "does not allow a string" do
+ expect { resource.send(:values, "souffle") }.to raise_error(ArgumentError)
end
- it "should not allow an integer" do
- expect { @resource.send(:values, 100) }.to raise_error(ArgumentError)
+ it "does not allow an integer" do
+ expect { resource.send(:values, 100) }.to raise_error(ArgumentError)
end
- it "should raise an exception if type of name is not string" do
- expect { @resource.values([ { :name => 123, :type => :string, :data => "carmen" } ]) }.to raise_error(ArgumentError)
+ it "raises an exception if type of name is not string" do
+ expect { resource.values([ { :name => 123, :type => :string, :data => "carmen" } ]) }.to raise_error(ArgumentError)
end
- it "should not raise an exception if type of name is string" do
- expect { @resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error
+ it "does not raise an exception if type of name is string" do
+ expect { resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error
end
context "type key not given" do
- it "should not raise an exception" do
- expect { @resource.values([ { :name => "123", :data => "carmen" } ]) }.to_not raise_error
+ it "does not raise an exception" do
+ expect { resource.values([ { :name => "123", :data => "carmen" } ]) }.to_not raise_error
end
end
context "type key given" do
- it "should raise an exception if type of type is not symbol" do
- expect { @resource.values([ { :name => "123", :type => "string", :data => "carmen" } ]) }.to raise_error(ArgumentError)
+ it "raises an exception if type of type is not symbol" do
+ expect { resource.values([ { :name => "123", :type => "string", :data => "carmen" } ]) }.to raise_error(ArgumentError)
end
- it "should not raise an exception if type of type is symbol" do
- expect { @resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error
+ it "does not raise an exception if type of type is symbol" do
+ expect { resource.values([ { :name => "123", :type => :string, :data => "carmen" } ]) }.to_not raise_error
end
end
end
describe Chef::Resource::RegistryKey, "recursive" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
- it "should allow a boolean" do
- @resource.recursive(true)
- expect(@resource.recursive).to eql(true)
+ it "allows a boolean" do
+ resource.recursive(true)
+ expect(resource.recursive).to eql(true)
end
- it "should not allow a hash" do
- expect { @resource.recursive({ :sonic => :screwdriver }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.recursive({ :sonic => :screwdriver }) }.to raise_error(ArgumentError)
end
- it "should not allow an array" do
- expect { @resource.recursive([:nose, :chin]) }.to raise_error(ArgumentError)
+ it "does not allow an array" do
+ expect { resource.recursive([:nose, :chin]) }.to raise_error(ArgumentError)
end
- it "should not allow a string" do
- expect { @resource.recursive("souffle") }.to raise_error(ArgumentError)
+ it "does not allow a string" do
+ expect { resource.recursive("souffle") }.to raise_error(ArgumentError)
end
- it "should not allow an integer" do
- expect { @resource.recursive(100) }.to raise_error(ArgumentError)
+ it "does not allow an integer" do
+ expect { resource.recursive(100) }.to raise_error(ArgumentError)
end
end
describe Chef::Resource::RegistryKey, "architecture" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
[ :i386, :x86_64, :machine ].each do |arch|
- it "should allow #{arch} as a symbol" do
- @resource.architecture(arch)
- expect(@resource.architecture).to eql(arch)
+ it "allows #{arch} as a symbol" do
+ resource.architecture(arch)
+ expect(resource.architecture).to eql(arch)
end
end
- it "should not allow a hash" do
- expect { @resource.architecture({ :sonic => :screwdriver }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.architecture({ :sonic => :screwdriver }) }.to raise_error(ArgumentError)
end
- it "should not allow an array" do
- expect { @resource.architecture([:nose, :chin]) }.to raise_error(ArgumentError)
+ it "does not allow an array" do
+ expect { resource.architecture([:nose, :chin]) }.to raise_error(ArgumentError)
end
- it "should not allow a string" do
- expect { @resource.architecture("souffle") }.to raise_error(ArgumentError)
+ it "does not allow a string" do
+ expect { resource.architecture("souffle") }.to raise_error(ArgumentError)
end
- it "should not allow an integer" do
- expect { @resource.architecture(100) }.to raise_error(ArgumentError)
+ it "does not allow an integer" do
+ expect { resource.architecture(100) }.to raise_error(ArgumentError)
end
end
describe Chef::Resource::RegistryKey, ":unscrubbed_values" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
- it "should return unsafe data as-is" do
+ it "returns unsafe data as-is" do
key_values = [ { :name => "poosh", :type => :binary, :data => 255.chr * 1 } ]
- @resource.values(key_values)
- expect(@resource.unscrubbed_values).to eql(key_values)
+ resource.values(key_values)
+ expect(resource.unscrubbed_values).to eql(key_values)
end
end
describe Chef::Resource::RegistryKey, "state" do
- before(:each) do
- @resource = Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius')
- end
+ let(:resource) { Chef::Resource::RegistryKey.new('HKCU\Software\Raxicoricofallapatorius') }
- it "should return scrubbed values" do
- @resource.values([ { :name => "poosh", :type => :binary, :data => 255.chr * 1 } ])
- expect(@resource.state_for_resource_reporter).to eql( { :values => [{ :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" }] } )
+ it "returns scrubbed values" do
+ resource.values([ { :name => "poosh", :type => :binary, :data => 255.chr * 1 } ])
+ expect(resource.state_for_resource_reporter).to eql( { :values => [{ :name => "poosh", :type => :binary, :data => "a8100ae6aa1940d0b663bb31cd466142ebbdbd5187131b92d93818987832eb89" }] } )
end
end
diff --git a/spec/unit/resource/remote_directory_spec.rb b/spec/unit/resource/remote_directory_spec.rb
index 370b8d8225..c016213c4a 100644
--- a/spec/unit/resource/remote_directory_spec.rb
+++ b/spec/unit/resource/remote_directory_spec.rb
@@ -20,78 +20,71 @@ require "spec_helper"
describe Chef::Resource::RemoteDirectory do
- before(:each) do
- @resource = Chef::Resource::RemoteDirectory.new("/etc/dunk")
- end
-
- it "should create a new Chef::Resource::RemoteDirectory" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::RemoteDirectory)
- end
+ let(:resource) { Chef::Resource::RemoteDirectory.new("/etc/dunk") }
- it "should set the path to the first argument to new" do
- expect(@resource.path).to eql("/etc/dunk")
+ it "sets the path to the first argument to new" do
+ expect(resource.path).to eql("/etc/dunk")
end
- it "should accept a string for the remote directory source" do
- @resource.source "foo"
- expect(@resource.source).to eql("foo")
+ it "accepts a string for the remote directory source" do
+ resource.source "foo"
+ expect(resource.source).to eql("foo")
end
- it "should have the basename of the remote directory resource as the default source" do
- expect(@resource.source).to eql("dunk")
+ it "has the basename of the remote directory resource as the default source" do
+ expect(resource.source).to eql("dunk")
end
- it "should accept a number for the remote files backup" do
- @resource.files_backup 1
- expect(@resource.files_backup).to eql(1)
+ it "accepts a number for the remote files backup" do
+ resource.files_backup 1
+ expect(resource.files_backup).to eql(1)
end
- it "should accept false for the remote files backup" do
- @resource.files_backup false
- expect(@resource.files_backup).to eql(false)
+ it "accepts false for the remote files backup" do
+ resource.files_backup false
+ expect(resource.files_backup).to eql(false)
end
- it "should accept 3 or 4 digets for the files_mode" do
- @resource.files_mode 100
- expect(@resource.files_mode).to eql(100)
- @resource.files_mode 1000
- expect(@resource.files_mode).to eql(1000)
+ it "accepts 3 or 4 digets for the files_mode" do
+ resource.files_mode 100
+ expect(resource.files_mode).to eql(100)
+ resource.files_mode 1000
+ expect(resource.files_mode).to eql(1000)
end
- it "should accept a string or number for the files group" do
- @resource.files_group "heart"
- expect(@resource.files_group).to eql("heart")
- @resource.files_group 1000
- expect(@resource.files_group).to eql(1000)
+ it "accepts a string or number for the files group" do
+ resource.files_group "heart"
+ expect(resource.files_group).to eql("heart")
+ resource.files_group 1000
+ expect(resource.files_group).to eql(1000)
end
- it "should accept a string or number for the files owner" do
- @resource.files_owner "heart"
- expect(@resource.files_owner).to eql("heart")
- @resource.files_owner 1000
- expect(@resource.files_owner).to eql(1000)
+ it "accepts a string or number for the files owner" do
+ resource.files_owner "heart"
+ expect(resource.files_owner).to eql("heart")
+ resource.files_owner 1000
+ expect(resource.files_owner).to eql(1000)
end
describe "when it has cookbook, files owner, files mode, and source" do
before do
- @resource.path("/var/path/")
- @resource.cookbook("pokemon.rb")
- @resource.files_owner("root")
- @resource.files_group("supergroup")
- @resource.files_mode("0664")
- @resource.source("/var/source/")
+ resource.path("/var/path/")
+ resource.cookbook("pokemon.rb")
+ resource.files_owner("root")
+ resource.files_group("supergroup")
+ resource.files_mode("0664")
+ resource.source("/var/source/")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:files_owner]).to eq("root")
expect(state[:files_group]).to eq("supergroup")
expect(state[:files_mode]).to eq("0664")
end
it "returns the path as its identity" do
- expect(@resource.identity).to eq("/var/path/")
+ expect(resource.identity).to eq("/var/path/")
end
end
end
diff --git a/spec/unit/resource/remote_file_spec.rb b/spec/unit/resource/remote_file_spec.rb
index eca3db3420..3e9ba1904c 100644
--- a/spec/unit/resource/remote_file_spec.rb
+++ b/spec/unit/resource/remote_file_spec.rb
@@ -21,147 +21,143 @@ require "spec_helper"
describe Chef::Resource::RemoteFile do
- before(:each) do
- @resource = Chef::Resource::RemoteFile.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::RemoteFile.new("fakey_fakerton") }
describe "initialize" do
- it "should create a new Chef::Resource::RemoteFile" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::File)
- expect(@resource).to be_a_kind_of(Chef::Resource::RemoteFile)
+ it "is a subclass of Chef::Resource::File" do
+ expect(resource).to be_a_kind_of(Chef::Resource::File)
end
end
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(@resource.provider_for_action(:create)).to be_kind_of(Chef::Provider::RemoteFile)
+ resource.source("http://www.google.com/robots.txt")
+ expect(resource.provider).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(@resource.provider_for_action(:create)).to be_kind_of(Chef::Provider::RemoteFile)
+ resource.source("\\\\fakey\\fakerton\\fake.txt")
+ expect(resource.provider).to eq(Chef::Provider::RemoteFile)
+ expect(resource.provider_for_action(:create)).to be_kind_of(Chef::Provider::RemoteFile)
end
describe "source" do
it "does not have a default value for 'source'" do
- expect(@resource.source).to eql([])
+ expect(resource.source).to eql([])
end
- it "should accept a URI for the remote file source" do
- @resource.source "http://opscode.com/"
- expect(@resource.source).to eql([ "http://opscode.com/" ])
+ it "accepts a URI for the remote file source" do
+ resource.source "http://opscode.com/"
+ expect(resource.source).to eql([ "http://opscode.com/" ])
end
- it "should accept a windows network share source" do
- @resource.source "\\\\fakey\\fakerton\\fake.txt"
- expect(@resource.source).to eql([ "\\\\fakey\\fakerton\\fake.txt" ])
+ it "accepts a windows network share source" do
+ resource.source "\\\\fakey\\fakerton\\fake.txt"
+ expect(resource.source).to eql([ "\\\\fakey\\fakerton\\fake.txt" ])
end
- it "should accept file URIs with spaces" do
- @resource.source("file:///C:/foo bar")
- expect(@resource.source).to eql(["file:///C:/foo bar"])
+ it "accepts file URIs with spaces" do
+ resource.source("file:///C:/foo bar")
+ expect(resource.source).to eql(["file:///C:/foo bar"])
end
- it "should accept a delayed evalutator (string) for the remote file source" do
- @resource.source Chef::DelayedEvaluator.new { "http://opscode.com/" }
- expect(@resource.source).to eql([ "http://opscode.com/" ])
+ it "accepts a delayed evalutator (string) for the remote file source" do
+ resource.source Chef::DelayedEvaluator.new { "http://opscode.com/" }
+ expect(resource.source).to eql([ "http://opscode.com/" ])
end
- it "should accept an array of URIs for the remote file source" do
- @resource.source([ "http://opscode.com/", "http://puppetlabs.com/" ])
- expect(@resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
+ it "accepts an array of URIs for the remote file source" do
+ resource.source([ "http://opscode.com/", "http://puppetlabs.com/" ])
+ expect(resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
end
- it "should accept a delated evaluator (array) for the remote file source" do
- @resource.source Chef::DelayedEvaluator.new { [ "http://opscode.com/", "http://puppetlabs.com/" ] }
- expect(@resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
+ it "accepts a delated evaluator (array) for the remote file source" do
+ resource.source Chef::DelayedEvaluator.new { [ "http://opscode.com/", "http://puppetlabs.com/" ] }
+ expect(resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
end
- it "should accept an multiple URIs as arguments for the remote file source" do
- @resource.source("http://opscode.com/", "http://puppetlabs.com/")
- expect(@resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
+ it "accepts an multiple URIs as arguments for the remote file source" do
+ resource.source("http://opscode.com/", "http://puppetlabs.com/")
+ expect(resource.source).to eql([ "http://opscode.com/", "http://puppetlabs.com/" ])
end
- it "should only accept a single argument if a delayed evalutor is used" do
+ it "only accept a single argument if a delayed evalutor is used" do
expect do
- @resource.source("http://opscode.com/", Chef::DelayedEvaluator.new { "http://opscode.com/" })
+ resource.source("http://opscode.com/", Chef::DelayedEvaluator.new { "http://opscode.com/" })
end.to raise_error(Chef::Exceptions::InvalidRemoteFileURI)
end
- it "should only accept a single array item if a delayed evalutor is used" do
+ it "only accept a single array item if a delayed evalutor is used" do
expect do
- @resource.source(["http://opscode.com/", Chef::DelayedEvaluator.new { "http://opscode.com/" }])
+ resource.source(["http://opscode.com/", Chef::DelayedEvaluator.new { "http://opscode.com/" }])
end.to raise_error(Chef::Exceptions::InvalidRemoteFileURI)
end
it "does not accept a non-URI as the source" do
- expect { @resource.source("not-a-uri") }.to raise_error(Chef::Exceptions::InvalidRemoteFileURI)
+ expect { resource.source("not-a-uri") }.to raise_error(Chef::Exceptions::InvalidRemoteFileURI)
end
it "does not accept a non-URI as the source when read from a delayed evaluator" do
expect do
- @resource.source(Chef::DelayedEvaluator.new { "not-a-uri" })
- @resource.source
+ resource.source(Chef::DelayedEvaluator.new { "not-a-uri" })
+ resource.source
end.to raise_error(Chef::Exceptions::InvalidRemoteFileURI)
end
- it "should raise an exception when source is an empty array" do
- expect { @resource.source([]) }.to raise_error(ArgumentError)
+ it "raises an exception when source is an empty array" do
+ expect { resource.source([]) }.to raise_error(ArgumentError)
end
end
describe "checksum" do
- it "should accept a string for the checksum object" do
- @resource.checksum "asdf"
- expect(@resource.checksum).to eql("asdf")
+ it "accepts a string for the checksum object" do
+ resource.checksum "asdf"
+ expect(resource.checksum).to eql("asdf")
end
- it "should default to nil" do
- expect(@resource.checksum).to eq(nil)
+ it "defaults to nil" do
+ expect(resource.checksum).to eq(nil)
end
end
describe "ftp_active_mode" do
- it "should accept a boolean for the ftp_active_mode object" do
- @resource.ftp_active_mode true
- expect(@resource.ftp_active_mode).to be_truthy
+ it "accepts a boolean for the ftp_active_mode object" do
+ resource.ftp_active_mode true
+ expect(resource.ftp_active_mode).to be_truthy
end
- it "should default to false" do
- expect(@resource.ftp_active_mode).to be_falsey
+ it "defaults to false" do
+ expect(resource.ftp_active_mode).to be_falsey
end
end
describe "conditional get options" do
it "defaults to using etags and last modified" do
- expect(@resource.use_etags).to be_truthy
- expect(@resource.use_last_modified).to be_truthy
+ expect(resource.use_etags).to be_truthy
+ expect(resource.use_last_modified).to be_truthy
end
it "enable or disables etag and last modified options as a group" do
- @resource.use_conditional_get(false)
- expect(@resource.use_etags).to be_falsey
- expect(@resource.use_last_modified).to be_falsey
+ resource.use_conditional_get(false)
+ expect(resource.use_etags).to be_falsey
+ expect(resource.use_last_modified).to be_falsey
- @resource.use_conditional_get(true)
- expect(@resource.use_etags).to be_truthy
- expect(@resource.use_last_modified).to be_truthy
+ resource.use_conditional_get(true)
+ expect(resource.use_etags).to be_truthy
+ expect(resource.use_last_modified).to be_truthy
end
it "disables etags indivdually" do
- @resource.use_etags(false)
- expect(@resource.use_etags).to be_falsey
- expect(@resource.use_last_modified).to be_truthy
+ resource.use_etags(false)
+ expect(resource.use_etags).to be_falsey
+ expect(resource.use_last_modified).to be_truthy
end
it "disables last modified individually" do
- @resource.use_last_modified(false)
- expect(@resource.use_last_modified).to be_falsey
- expect(@resource.use_etags).to be_truthy
+ resource.use_last_modified(false)
+ expect(resource.use_last_modified).to be_falsey
+ expect(resource.use_etags).to be_truthy
end
end
@@ -169,21 +165,21 @@ describe Chef::Resource::RemoteFile do
describe "when it has group, mode, owner, source, and checksum" do
before do
if Chef::Platform.windows?
- @resource.path("C:/temp/origin/file.txt")
- @resource.rights(:read, "Everyone")
- @resource.deny_rights(:full_control, "Clumsy_Sam")
+ resource.path("C:/temp/origin/file.txt")
+ resource.rights(:read, "Everyone")
+ resource.deny_rights(:full_control, "Clumsy_Sam")
else
- @resource.path("/this/path/")
- @resource.group("pokemon")
- @resource.mode("0664")
- @resource.owner("root")
+ resource.path("/this/path/")
+ resource.group("pokemon")
+ resource.mode("0664")
+ resource.owner("root")
end
- @resource.source("https://www.google.com/images/srpr/logo3w.png")
- @resource.checksum("1" * 26)
+ resource.source("https://www.google.com/images/srpr/logo3w.png")
+ resource.checksum("1" * 26)
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
if Chef::Platform.windows?
puts state
expect(state[:rights]).to eq([{ :permissions => :read, :principals => "Everyone" }])
@@ -198,9 +194,9 @@ describe Chef::Resource::RemoteFile do
it "returns the path as its identity" do
if Chef::Platform.windows?
- expect(@resource.identity).to eq("C:/temp/origin/file.txt")
+ expect(resource.identity).to eq("C:/temp/origin/file.txt")
else
- expect(@resource.identity).to eq("/this/path/")
+ expect(resource.identity).to eq("/this/path/")
end
end
end
diff --git a/spec/unit/resource/route_spec.rb b/spec/unit/resource/route_spec.rb
index 884b477365..899012b9dc 100644
--- a/spec/unit/resource/route_spec.rb
+++ b/spec/unit/resource/route_spec.rb
@@ -21,87 +21,80 @@ require "spec_helper"
describe Chef::Resource::Route do
- before(:each) do
- @resource = Chef::Resource::Route.new("10.0.0.10")
- end
-
- it "should create a new Chef::Resource::Route" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Route)
- end
+ let(:resource) { Chef::Resource::Route.new("10.0.0.10") }
- it "should have a name" do
- expect(@resource.name).to eql("10.0.0.10")
+ it "has a name property" do
+ expect(resource.name).to eql("10.0.0.10")
end
- it "should have a default action of 'add'" do
- expect(@resource.action).to eql([:add])
+ it "has a default action of 'add'" do
+ expect(resource.action).to eql([:add])
end
- it "should accept add or delete for action" do
- expect { @resource.action :add }.not_to raise_error
- expect { @resource.action :delete }.not_to raise_error
- expect { @resource.action :lolcat }.to raise_error(ArgumentError)
+ it "accepts add or delete for action" do
+ expect { resource.action :add }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ expect { resource.action :lolcat }.to raise_error(ArgumentError)
end
- it "should use the object name as the target by default" do
- expect(@resource.target).to eql("10.0.0.10")
+ it "uses the object name as the target by default" do
+ expect(resource.target).to eql("10.0.0.10")
end
- it "should allow you to specify the netmask" do
- @resource.netmask "255.255.255.0"
- expect(@resource.netmask).to eql("255.255.255.0")
+ it "allows you to specify the netmask" do
+ resource.netmask "255.255.255.0"
+ expect(resource.netmask).to eql("255.255.255.0")
end
- it "should allow you to specify the gateway" do
- @resource.gateway "10.0.0.1"
- expect(@resource.gateway).to eql("10.0.0.1")
+ it "allows you to specify the gateway" do
+ resource.gateway "10.0.0.1"
+ expect(resource.gateway).to eql("10.0.0.1")
end
- it "should allow you to specify the metric" do
- @resource.metric 10
- expect(@resource.metric).to eql(10)
+ it "allows you to specify the metric" do
+ resource.metric 10
+ expect(resource.metric).to eql(10)
end
- it "should allow you to specify the device" do
- @resource.device "eth0"
- expect(@resource.device).to eql("eth0")
+ it "allows you to specify the device" do
+ resource.device "eth0"
+ expect(resource.device).to eql("eth0")
end
- it "should allow you to specify the route type" do
- @resource.route_type "host"
- expect(@resource.route_type).to eql(:host)
+ it "allows you to specify the route type" do
+ resource.route_type "host"
+ expect(resource.route_type).to eql(:host)
end
- it "should default to a host route type" do
- expect(@resource.route_type).to eql(:host)
+ it "defaults to a host route type" do
+ expect(resource.route_type).to eql(:host)
end
- it "should accept a net route type" do
- @resource.route_type :net
- expect(@resource.route_type).to eql(:net)
+ it "accepts a net route type" do
+ resource.route_type :net
+ expect(resource.route_type).to eql(:net)
end
- it "should reject any other route_type but :host and :net" do
- expect { @resource.route_type "lolcat" }.to raise_error(ArgumentError)
+ it "rejects any other route_type but :host and :net" do
+ expect { resource.route_type "lolcat" }.to raise_error(ArgumentError)
end
describe "when it has netmask, gateway, and device" do
before do
- @resource.target("charmander")
- @resource.netmask("lemask")
- @resource.gateway("111.111.111")
- @resource.device("forcefield")
+ resource.target("charmander")
+ resource.netmask("lemask")
+ resource.gateway("111.111.111")
+ resource.device("forcefield")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:netmask]).to eq("lemask")
expect(state[:gateway]).to eq("111.111.111")
end
it "returns the target as its identity" do
- expect(@resource.identity).to eq("charmander")
+ expect(resource.identity).to eq("charmander")
end
end
end
diff --git a/spec/unit/resource/rpm_package_spec.rb b/spec/unit/resource/rpm_package_spec.rb
index e1488f1dd1..0104e10dae 100644
--- a/spec/unit/resource/rpm_package_spec.rb
+++ b/spec/unit/resource/rpm_package_spec.rb
@@ -34,13 +34,15 @@ describe Chef::Resource::RpmPackage, "initialize" do
end
describe Chef::Resource::RpmPackage, "allow_downgrade" do
- before(:each) do
- @resource = Chef::Resource::RpmPackage.new("foo")
+ let(:resource) { Chef::Resource::RpmPackage.new("foo") }
+
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
end
- it "should allow you to specify whether allow_downgrade is true or false" do
- expect { @resource.allow_downgrade true }.not_to raise_error
- expect { @resource.allow_downgrade false }.not_to raise_error
- expect { @resource.allow_downgrade "monkey" }.to raise_error(ArgumentError)
+ it "allows you to specify whether allow_downgrade is true or false" do
+ expect { resource.allow_downgrade true }.not_to raise_error
+ expect { resource.allow_downgrade false }.not_to raise_error
+ expect { resource.allow_downgrade "monkey" }.to raise_error(ArgumentError)
end
end
diff --git a/spec/unit/resource/ruby_block_spec.rb b/spec/unit/resource/ruby_block_spec.rb
index f393fbea46..fd0da32123 100644
--- a/spec/unit/resource/ruby_block_spec.rb
+++ b/spec/unit/resource/ruby_block_spec.rb
@@ -21,41 +21,34 @@ require "spec_helper"
describe Chef::Resource::RubyBlock do
- before(:each) do
- @resource = Chef::Resource::RubyBlock.new("fakey_fakerton")
- end
-
- it "should create a new Chef::Resource::RubyBlock" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::RubyBlock)
- end
+ let(:resource) { Chef::Resource::RubyBlock.new("fakey_fakerton") }
- it "should have a default action of 'run'" do
- expect(@resource.action).to eql([:run])
+ it "has a default action of 'run'" do
+ expect(resource.action).to eql([:run])
end
- it "should have a resource name of :ruby_block" do
- expect(@resource.resource_name).to eql(:ruby_block)
+ it "has a resource name of :ruby_block" do
+ expect(resource.resource_name).to eql(:ruby_block)
end
- it "should accept a ruby block/proc/.. for the 'block' parameter" do
- expect(@resource.block do
+ it "accepts a ruby block/proc/.. for the 'block' parameter" do
+ expect(resource.block do
"foo"
end.call).to eql("foo")
end
it "allows the action to be 'create'" do
- @resource.action :create
- expect(@resource.action).to eq([:create])
+ resource.action :create
+ expect(resource.action).to eq([:create])
end
describe "when it has been initialized with block code" do
before do
- @resource.block_name("puts 'harrrr'")
+ resource.block_name("puts 'harrrr'")
end
it "returns the block as its identity" do
- expect(@resource.identity).to eq("puts 'harrrr'")
+ expect(resource.identity).to eq("puts 'harrrr'")
end
end
end
diff --git a/spec/unit/resource/ruby_spec.rb b/spec/unit/resource/ruby_spec.rb
index d7b6759462..4327917295 100644
--- a/spec/unit/resource/ruby_spec.rb
+++ b/spec/unit/resource/ruby_spec.rb
@@ -19,22 +19,13 @@
require "spec_helper"
describe Chef::Resource::Ruby do
+ let(:resource) { Chef::Resource::Ruby.new("fakey_fakerton") }
- before(:each) do
- @resource = Chef::Resource::Ruby.new("fakey_fakerton")
+ it "has a resource name of :ruby" do
+ expect(resource.resource_name).to eql(:ruby)
end
- it "should create a new Chef::Resource::Ruby" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Ruby)
+ it "has an interpreter of ruby" do
+ expect(resource.interpreter).to eql("ruby")
end
-
- it "should have a resource name of :ruby" do
- expect(@resource.resource_name).to eql(:ruby)
- end
-
- it "should have an interpreter of ruby" do
- expect(@resource.interpreter).to eql("ruby")
- end
-
end
diff --git a/spec/unit/resource/scm_spec.rb b/spec/unit/resource/scm_spec.rb
index 679b3bc1fc..cffc956960 100644
--- a/spec/unit/resource/scm_spec.rb
+++ b/spec/unit/resource/scm_spec.rb
@@ -20,174 +20,167 @@
require "spec_helper"
describe Chef::Resource::Scm do
-
- before(:each) do
- @resource = Chef::Resource::Scm.new("my awesome app")
- end
-
- it "should be a SCM resource" do
- expect(@resource).to be_a_kind_of(Chef::Resource::Scm)
- end
+ let(:resource) { Chef::Resource::Scm.new("my awesome app") }
it "supports :checkout, :export, :sync, :diff, and :log actions" do
- expect(@resource.allowed_actions).to include(:checkout)
- expect(@resource.allowed_actions).to include(:export)
- expect(@resource.allowed_actions).to include(:sync)
- expect(@resource.allowed_actions).to include(:diff)
- expect(@resource.allowed_actions).to include(:log)
+ expect(resource.allowed_actions).to include(:checkout)
+ expect(resource.allowed_actions).to include(:export)
+ expect(resource.allowed_actions).to include(:sync)
+ expect(resource.allowed_actions).to include(:diff)
+ expect(resource.allowed_actions).to include(:log)
end
it "takes the destination path as a string" do
- @resource.destination "/path/to/deploy/dir"
- expect(@resource.destination).to eql("/path/to/deploy/dir")
+ resource.destination "/path/to/deploy/dir"
+ expect(resource.destination).to eql("/path/to/deploy/dir")
end
it "takes a string for the repository URL" do
- @resource.repository "git://github.com/opscode/chef.git"
- expect(@resource.repository).to eql("git://github.com/opscode/chef.git")
+ resource.repository "git://github.com/opscode/chef.git"
+ expect(resource.repository).to eql("git://github.com/opscode/chef.git")
end
it "takes a string for the revision" do
- @resource.revision "abcdef"
- expect(@resource.revision).to eql("abcdef")
+ resource.revision "abcdef"
+ expect(resource.revision).to eql("abcdef")
end
it "defaults to the ``HEAD'' revision" do
- expect(@resource.revision).to eql("HEAD")
+ expect(resource.revision).to eql("HEAD")
end
it "takes a string for the user to run as" do
- @resource.user "dr_deploy"
- expect(@resource.user).to eql("dr_deploy")
+ resource.user "dr_deploy"
+ expect(resource.user).to eql("dr_deploy")
end
it "also takes an integer for the user to run as" do
- @resource.user 0
- expect(@resource.user).to eql(0)
+ resource.user 0
+ expect(resource.user).to eql(0)
end
it "takes a string for the group to run as, defaulting to nil" do
- expect(@resource.group).to be_nil
- @resource.group "opsdevs"
- expect(@resource.group).to eq("opsdevs")
+ expect(resource.group).to be_nil
+ resource.group "opsdevs"
+ expect(resource.group).to eq("opsdevs")
end
it "also takes an integer for the group to run as" do
- @resource.group 23
- expect(@resource.group).to eq(23)
+ resource.group 23
+ expect(resource.group).to eq(23)
end
it "has a svn_username String attribute" do
- @resource.svn_username "moartestsplz"
- expect(@resource.svn_username).to eql("moartestsplz")
+ resource.svn_username "moartestsplz"
+ expect(resource.svn_username).to eql("moartestsplz")
end
it "has a svn_password String attribute" do
- @resource.svn_password "taftplz"
- expect(@resource.svn_password).to eql("taftplz")
+ resource.svn_password "taftplz"
+ expect(resource.svn_password).to eql("taftplz")
end
it "has a svn_arguments String attribute" do
- @resource.svn_arguments "--more-taft plz"
- expect(@resource.svn_arguments).to eql("--more-taft plz")
+ resource.svn_arguments "--more-taft plz"
+ expect(resource.svn_arguments).to eql("--more-taft plz")
end
it "has a svn_info_args String attribute" do
- expect(@resource.svn_info_args).to be_nil
- @resource.svn_info_args("--no-moar-plaintext-creds yep")
- expect(@resource.svn_info_args).to eq("--no-moar-plaintext-creds yep")
+ expect(resource.svn_info_args).to be_nil
+ resource.svn_info_args("--no-moar-plaintext-creds yep")
+ expect(resource.svn_info_args).to eq("--no-moar-plaintext-creds yep")
end
it "takes the depth as an integer for shallow clones" do
- @resource.depth 5
- expect(@resource.depth).to eq(5)
- expect { @resource.depth "five" }.to raise_error(ArgumentError)
+ resource.depth 5
+ expect(resource.depth).to eq(5)
+ expect { resource.depth "five" }.to raise_error(ArgumentError)
end
it "defaults to nil depth for a full clone" do
- expect(@resource.depth).to be_nil
+ expect(resource.depth).to be_nil
end
it "takes a boolean for #enable_submodules" do
- @resource.enable_submodules true
- expect(@resource.enable_submodules).to be_truthy
- expect { @resource.enable_submodules "lolz" }.to raise_error(ArgumentError)
+ resource.enable_submodules true
+ expect(resource.enable_submodules).to be_truthy
+ expect { resource.enable_submodules "lolz" }.to raise_error(ArgumentError)
end
it "defaults to not enabling submodules" do
- expect(@resource.enable_submodules).to be_falsey
+ expect(resource.enable_submodules).to be_falsey
end
it "takes a boolean for #enable_checkout" do
- @resource.enable_checkout true
- expect(@resource.enable_checkout).to be_truthy
- expect { @resource.enable_checkout "lolz" }.to raise_error(ArgumentError)
+ resource.enable_checkout true
+ expect(resource.enable_checkout).to be_truthy
+ expect { resource.enable_checkout "lolz" }.to raise_error(ArgumentError)
end
it "defaults to enabling checkout" do
- expect(@resource.enable_checkout).to be_truthy
+ expect(resource.enable_checkout).to be_truthy
end
it "takes a string for the remote" do
- @resource.remote "opscode"
- expect(@resource.remote).to eql("opscode")
- expect { @resource.remote 1337 }.to raise_error(ArgumentError)
+ resource.remote "opscode"
+ expect(resource.remote).to eql("opscode")
+ expect { resource.remote 1337 }.to raise_error(ArgumentError)
end
it "defaults to ``origin'' for the remote" do
- expect(@resource.remote).to eq("origin")
+ expect(resource.remote).to eq("origin")
end
it "takes a string for the ssh wrapper" do
- @resource.ssh_wrapper "with_ssh_fu"
- expect(@resource.ssh_wrapper).to eql("with_ssh_fu")
+ resource.ssh_wrapper "with_ssh_fu"
+ expect(resource.ssh_wrapper).to eql("with_ssh_fu")
end
it "defaults to nil for the ssh wrapper" do
- expect(@resource.ssh_wrapper).to be_nil
+ expect(resource.ssh_wrapper).to be_nil
end
it "defaults to nil for the environment" do
- expect(@resource.environment).to be_nil
+ expect(resource.environment).to be_nil
end
describe "when it has a timeout attribute" do
let(:ten_seconds) { 10 }
- before { @resource.timeout(ten_seconds) }
+ before { resource.timeout(ten_seconds) }
it "stores this timeout" do
- expect(@resource.timeout).to eq(ten_seconds)
+ expect(resource.timeout).to eq(ten_seconds)
end
end
describe "when it has no timeout attribute" do
- it "should have no default timeout" do
- expect(@resource.timeout).to be_nil
+ it "has no default timeout" do
+ expect(resource.timeout).to be_nil
end
end
describe "when it has repository, revision, user, and group" do
before do
- @resource.destination("hell")
- @resource.repository("apt")
- @resource.revision("1.2.3")
- @resource.user("root")
- @resource.group("super_adventure_club")
+ resource.destination("hell")
+ resource.repository("apt")
+ resource.revision("1.2.3")
+ resource.user("root")
+ resource.group("super_adventure_club")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:revision]).to eq("1.2.3")
end
it "returns the destination as its identity" do
- expect(@resource.identity).to eq("hell")
+ expect(resource.identity).to eq("hell")
end
end
describe "when it has a environment attribute" do
let(:test_environment) { { "CHEF_ENV" => "/tmp" } }
- before { @resource.environment(test_environment) }
+ before { resource.environment(test_environment) }
it "stores this environment" do
- expect(@resource.environment).to eq(test_environment)
+ expect(resource.environment).to eq(test_environment)
end
end
end
diff --git a/spec/unit/resource/script_spec.rb b/spec/unit/resource/script_spec.rb
index 16f7650712..554d99710e 100644
--- a/spec/unit/resource/script_spec.rb
+++ b/spec/unit/resource/script_spec.rb
@@ -24,7 +24,7 @@ describe Chef::Resource::Script do
let(:script_resource) { Chef::Resource::Script.new(resource_instance_name) }
let(:resource_name) { :script }
- it "should accept a string for the interpreter" do
+ it "accepts a string for the interpreter" do
script_resource.interpreter "naaaaNaNaNaaNaaNaaNaa"
expect(script_resource.interpreter).to eql("naaaaNaNaNaaNaaNaaNaa")
end
diff --git a/spec/unit/resource/service_spec.rb b/spec/unit/resource/service_spec.rb
index 67a4635983..335ad76fc8 100644
--- a/spec/unit/resource/service_spec.rb
+++ b/spec/unit/resource/service_spec.rb
@@ -20,180 +20,172 @@
require "spec_helper"
describe Chef::Resource::Service do
+ let(:resource) { Chef::Resource::Service.new("chef") }
- before(:each) do
- @resource = Chef::Resource::Service.new("chef")
+ it "does not set a provider unless node[:init_package] is defined as systemd" do
+ expect(resource.provider).to eq(nil)
end
- it "should create a new Chef::Resource::Service" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::Service)
+ it "sets the service_name to the first argument to new" do
+ expect(resource.service_name).to eql("chef")
end
- it "should not set a provider unless node[:init_package] is defined as systemd" do
- expect(@resource.provider).to eq(nil)
+ it "sets the pattern to be the service name by default" do
+ expect(resource.pattern).to eql("chef")
end
- it "should set the service_name to the first argument to new" do
- expect(@resource.service_name).to eql("chef")
+ it "accepts a string for the service name" do
+ resource.service_name "something"
+ expect(resource.service_name).to eql("something")
end
- it "should set the pattern to be the service name by default" do
- expect(@resource.pattern).to eql("chef")
+ it "accepts a string for the service pattern" do
+ resource.pattern ".*"
+ expect(resource.pattern).to eql(".*")
end
- it "should accept a string for the service name" do
- @resource.service_name "something"
- expect(@resource.service_name).to eql("something")
- end
-
- it "should accept a string for the service pattern" do
- @resource.pattern ".*"
- expect(@resource.pattern).to eql(".*")
- end
-
- it "should not accept a regexp for the service pattern" do
+ it "does not accept a regexp for the service pattern" do
expect do
- @resource.pattern /.*/
+ resource.pattern /.*/
end.to raise_error(ArgumentError)
end
- it "should accept a string for the service start command" do
- @resource.start_command "/etc/init.d/chef start"
- expect(@resource.start_command).to eql("/etc/init.d/chef start")
+ it "accepts a string for the service start command" do
+ resource.start_command "/etc/init.d/chef start"
+ expect(resource.start_command).to eql("/etc/init.d/chef start")
end
- it "should not accept a regexp for the service start command" do
+ it "does not accept a regexp for the service start command" do
expect do
- @resource.start_command /.*/
+ resource.start_command /.*/
end.to raise_error(ArgumentError)
end
- it "should accept a string for the service stop command" do
- @resource.stop_command "/etc/init.d/chef stop"
- expect(@resource.stop_command).to eql("/etc/init.d/chef stop")
+ it "accepts a string for the service stop command" do
+ resource.stop_command "/etc/init.d/chef stop"
+ expect(resource.stop_command).to eql("/etc/init.d/chef stop")
end
- it "should not accept a regexp for the service stop command" do
+ it "does not accept a regexp for the service stop command" do
expect do
- @resource.stop_command /.*/
+ resource.stop_command /.*/
end.to raise_error(ArgumentError)
end
- it "should accept a string for the service status command" do
- @resource.status_command "/etc/init.d/chef status"
- expect(@resource.status_command).to eql("/etc/init.d/chef status")
+ it "accepts a string for the service status command" do
+ resource.status_command "/etc/init.d/chef status"
+ expect(resource.status_command).to eql("/etc/init.d/chef status")
end
- it "should not accept a regexp for the service status command" do
+ it "does not accept a regexp for the service status command" do
expect do
- @resource.status_command /.*/
+ resource.status_command /.*/
end.to raise_error(ArgumentError)
end
- it "should accept a string for the service restart command" do
- @resource.restart_command "/etc/init.d/chef restart"
- expect(@resource.restart_command).to eql("/etc/init.d/chef restart")
+ it "accepts a string for the service restart command" do
+ resource.restart_command "/etc/init.d/chef restart"
+ expect(resource.restart_command).to eql("/etc/init.d/chef restart")
end
- it "should not accept a regexp for the service restart command" do
+ it "does not accept a regexp for the service restart command" do
expect do
- @resource.restart_command /.*/
+ resource.restart_command /.*/
end.to raise_error(ArgumentError)
end
- it "should accept a string for the service reload command" do
- @resource.reload_command "/etc/init.d/chef reload"
- expect(@resource.reload_command).to eql("/etc/init.d/chef reload")
+ it "accepts a string for the service reload command" do
+ resource.reload_command "/etc/init.d/chef reload"
+ expect(resource.reload_command).to eql("/etc/init.d/chef reload")
end
- it "should not accept a regexp for the service reload command" do
+ it "does not accept a regexp for the service reload command" do
expect do
- @resource.reload_command /.*/
+ resource.reload_command /.*/
end.to raise_error(ArgumentError)
end
- it "should accept a string for the service init command" do
- @resource.init_command "/etc/init.d/chef"
- expect(@resource.init_command).to eql("/etc/init.d/chef")
+ it "accepts a string for the service init command" do
+ resource.init_command "/etc/init.d/chef"
+ expect(resource.init_command).to eql("/etc/init.d/chef")
end
- it "should not accept a regexp for the service init command" do
+ it "does not accept a regexp for the service init command" do
expect do
- @resource.init_command /.*/
+ resource.init_command /.*/
end.to raise_error(ArgumentError)
end
- it "should accept an array for options" do
- @resource.options ["-r", "-s"]
- expect(@resource.options).to eql(["-r", "-s"])
+ it "accepts an array for options" do
+ resource.options ["-r", "-s"]
+ expect(resource.options).to eql(["-r", "-s"])
end
- it "should accept a string for options" do
- @resource.options "-r"
- expect(@resource.options).to eql(["-r"])
+ it "accepts a string for options" do
+ resource.options "-r"
+ expect(resource.options).to eql(["-r"])
end
- it "should accept a string with multiple flags for options" do
- @resource.options "-r -s"
- expect(@resource.options).to eql(["-r", "-s"])
+ it "accepts a string with multiple flags for options" do
+ resource.options "-r -s"
+ expect(resource.options).to eql(["-r", "-s"])
end
- it "should not accept a boolean for options" do
+ it "does not accept a boolean for options" do
expect do
- @resource.options true
+ resource.options true
end.to raise_error(ArgumentError)
end
%w{enabled running}.each do |attrib|
- it "should accept true for #{attrib}" do
- @resource.send(attrib, true)
- expect(@resource.send(attrib)).to eql(true)
+ it "accepts true for #{attrib}" do
+ resource.send(attrib, true)
+ expect(resource.send(attrib)).to eql(true)
end
- it "should accept false for #{attrib}" do
- @resource.send(attrib, false)
- expect(@resource.send(attrib)).to eql(false)
+ it "accepts false for #{attrib}" do
+ resource.send(attrib, false)
+ expect(resource.send(attrib)).to eql(false)
end
- it "should not accept a string for #{attrib}" do
- expect { @resource.send(attrib, "poop") }.to raise_error(ArgumentError)
+ it "does not accept a string for #{attrib}" do
+ expect { resource.send(attrib, "poop") }.to raise_error(ArgumentError)
end
- it "should default all the feature support to nil" do
+ it "defaults all the feature support to nil" do
support_hash = { :status => nil, :restart => nil, :reload => nil }
- expect(@resource.supports).to eq(support_hash)
+ expect(resource.supports).to eq(support_hash)
end
- it "should allow you to set what features this resource supports as a array" do
+ it "allows you to set what features this resource supports as a array" do
support_array = [ :status, :restart ]
support_hash = { :status => true, :restart => true }
- @resource.supports(support_array)
- expect(@resource.supports).to eq(support_hash)
+ resource.supports(support_array)
+ expect(resource.supports).to eq(support_hash)
end
- it "should allow you to set what features this resource supports as a hash" do
+ it "allows you to set what features this resource supports as a hash" do
support_hash = { :status => true, :restart => true }
- @resource.supports(support_hash)
- expect(@resource.supports).to eq(support_hash)
+ resource.supports(support_hash)
+ expect(resource.supports).to eq(support_hash)
end
end
describe "when it has pattern and supports" do
before do
- @resource.service_name("superfriend")
- @resource.enabled(true)
- @resource.running(false)
+ resource.service_name("superfriend")
+ resource.enabled(true)
+ resource.running(false)
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:enabled]).to eql(true)
expect(state[:running]).to eql(false)
end
it "returns the service name as its identity" do
- expect(@resource.identity).to eq("superfriend")
+ expect(resource.identity).to eq("superfriend")
end
end
end
diff --git a/spec/unit/resource/smartos_package_spec.rb b/spec/unit/resource/smartos_package_spec.rb
index 56c0fbdb8b..a0bd5853f5 100644
--- a/spec/unit/resource/smartos_package_spec.rb
+++ b/spec/unit/resource/smartos_package_spec.rb
@@ -30,4 +30,9 @@ describe Chef::Resource::SmartosPackage, "initialize" do
platform_family: "smartos"
)
+ let(:resource) { Chef::Resource::SmartosPackage.new("foo") }
+
+ it "sets the package_name to the name provided" do
+ expect(resource.package_name).to eql("foo")
+ end
end
diff --git a/spec/unit/resource/solaris_package_spec.rb b/spec/unit/resource/solaris_package_spec.rb
index 1f1ef4da30..dda8240af8 100644
--- a/spec/unit/resource/solaris_package_spec.rb
+++ b/spec/unit/resource/solaris_package_spec.rb
@@ -32,11 +32,9 @@ describe Chef::Resource::SolarisPackage, "initialize" do
)
end
- before(:each) do
- @resource = Chef::Resource::SolarisPackage.new("foo")
- end
+ let(:resource) { Chef::Resource::SolarisPackage.new("foo") }
- it "should set the package_name to the name provided" do
- expect(@resource.package_name).to eql("foo")
+ it "sets the package_name to the name provided" do
+ expect(resource.package_name).to eql("foo")
end
end
diff --git a/spec/unit/resource/subversion_spec.rb b/spec/unit/resource/subversion_spec.rb
index a2901bf53b..2b86587f1a 100644
--- a/spec/unit/resource/subversion_spec.rb
+++ b/spec/unit/resource/subversion_spec.rb
@@ -28,44 +28,46 @@ describe Chef::Resource::Subversion do
action: :install
)
- before do
- @svn = Chef::Resource::Subversion.new("ohai, svn project!")
- end
+ let(:resource) { Chef::Resource::Subversion.new("ohai, svn project!") }
it "is a subclass of Resource::Scm" do
- expect(@svn).to be_an_instance_of(Chef::Resource::Subversion)
- expect(@svn).to be_a_kind_of(Chef::Resource::Scm)
+ expect(resource).to be_an_instance_of(Chef::Resource::Subversion)
+ expect(resource).to be_a_kind_of(Chef::Resource::Scm)
+ end
+
+ it "set destination property to the name_property" do
+ expect(resource.destination).to eq("ohai, svn project!")
end
it "allows the force_export action" do
- expect(@svn.allowed_actions).to include(:force_export)
+ expect(resource.allowed_actions).to include(:force_export)
end
it "sets svn info arguments to --no-auth-cache by default" do
- expect(@svn.svn_info_args).to eq("--no-auth-cache")
+ expect(resource.svn_info_args).to eq("--no-auth-cache")
end
it "resets svn info arguments to nil when given false in the setter" do
- @svn.svn_info_args(false)
- expect(@svn.svn_info_args).to be_nil
+ resource.svn_info_args(false)
+ expect(resource.svn_info_args).to be_nil
end
it "sets svn arguments to --no-auth-cache by default" do
- expect(@svn.svn_arguments).to eq("--no-auth-cache")
+ expect(resource.svn_arguments).to eq("--no-auth-cache")
end
it "sets svn binary to nil by default" do
- expect(@svn.svn_binary).to be_nil
+ expect(resource.svn_binary).to be_nil
end
it "resets svn arguments to nil when given false in the setter" do
- @svn.svn_arguments(false)
- expect(@svn.svn_arguments).to be_nil
+ resource.svn_arguments(false)
+ expect(resource.svn_arguments).to be_nil
end
it "hides password from custom exception message" do
- @svn.svn_password "l33th4x0rpa$$w0rd"
- e = @svn.customize_exception(Chef::Exceptions::Exec.new "Exception with password #{@svn.svn_password}")
- expect(e.message.include?(@svn.svn_password)).to be_falsey
+ resource.svn_password "l33th4x0rpa$$w0rd"
+ e = resource.customize_exception(Chef::Exceptions::Exec.new "Exception with password #{resource.svn_password}")
+ expect(e.message.include?(resource.svn_password)).to be_falsey
end
end
diff --git a/spec/unit/resource/systemd_unit_spec.rb b/spec/unit/resource/systemd_unit_spec.rb
index ab1004fab0..9d156402a1 100644
--- a/spec/unit/resource/systemd_unit_spec.rb
+++ b/spec/unit/resource/systemd_unit_spec.rb
@@ -1,6 +1,6 @@
#
# Author:: Nathan Williams (<nath.e.will@gmail.com>)
-# Copyright:: Copyright 2016, Nathan Williams
+# Copyright:: Copyright 2016-2018, Nathan Williams
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,12 +19,8 @@
require "spec_helper"
describe Chef::Resource::SystemdUnit do
- before(:each) do
- @resource = Chef::Resource::SystemdUnit.new("sysstat-collect.timer")
- end
-
+ let(:resource) { Chef::Resource::SystemdUnit.new("sysstat-collect.timer") }
let(:unit_content_string) { "[Unit]\nDescription = Run system activity accounting tool every 10 minutes\n\n[Timer]\nOnCalendar = *:00/10\n\n[Install]\nWantedBy = sysstat.service\n" }
-
let(:unit_content_hash) do
{
"Unit" => {
@@ -39,77 +35,75 @@ describe Chef::Resource::SystemdUnit do
}
end
- it "creates a new Chef::Resource::SystemdUnit" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::SystemdUnit)
- end
-
- it "should have a name" do
- expect(@resource.name).to eql("sysstat-collect.timer")
+ it "has a name property" do
+ expect(resource.name).to eql("sysstat-collect.timer")
end
it "has a default action of nothing" do
- expect(@resource.action).to eql([:nothing])
+ expect(resource.action).to eql([:nothing])
end
it "supports appropriate unit actions" do
- expect { @resource.action :create }.not_to raise_error
- expect { @resource.action :delete }.not_to raise_error
- expect { @resource.action :enable }.not_to raise_error
- expect { @resource.action :disable }.not_to raise_error
- expect { @resource.action :mask }.not_to raise_error
- expect { @resource.action :unmask }.not_to raise_error
- expect { @resource.action :start }.not_to raise_error
- expect { @resource.action :stop }.not_to raise_error
- expect { @resource.action :restart }.not_to raise_error
- expect { @resource.action :reload }.not_to raise_error
- expect { @resource.action :wrong }.to raise_error(ArgumentError)
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :delete }.not_to raise_error
+ expect { resource.action :preset }.not_to raise_error
+ expect { resource.action :revert }.not_to raise_error
+ expect { resource.action :enable }.not_to raise_error
+ expect { resource.action :disable }.not_to raise_error
+ expect { resource.action :reenable }.not_to raise_error
+ expect { resource.action :mask }.not_to raise_error
+ expect { resource.action :unmask }.not_to raise_error
+ expect { resource.action :start }.not_to raise_error
+ expect { resource.action :stop }.not_to raise_error
+ expect { resource.action :restart }.not_to raise_error
+ expect { resource.action :reload }.not_to raise_error
+ expect { resource.action :wrong }.to raise_error(ArgumentError)
end
it "accepts boolean state properties" do
- expect { @resource.active false }.not_to raise_error
- expect { @resource.active true }.not_to raise_error
- expect { @resource.active "yes" }.to raise_error(ArgumentError)
+ expect { resource.active false }.not_to raise_error
+ expect { resource.active true }.not_to raise_error
+ expect { resource.active "yes" }.to raise_error(ArgumentError)
- expect { @resource.enabled true }.not_to raise_error
- expect { @resource.enabled false }.not_to raise_error
- expect { @resource.enabled "no" }.to raise_error(ArgumentError)
+ expect { resource.enabled true }.not_to raise_error
+ expect { resource.enabled false }.not_to raise_error
+ expect { resource.enabled "no" }.to raise_error(ArgumentError)
- expect { @resource.masked true }.not_to raise_error
- expect { @resource.masked false }.not_to raise_error
- expect { @resource.masked :nope }.to raise_error(ArgumentError)
+ expect { resource.masked true }.not_to raise_error
+ expect { resource.masked false }.not_to raise_error
+ expect { resource.masked :nope }.to raise_error(ArgumentError)
- expect { @resource.static true }.not_to raise_error
- expect { @resource.static false }.not_to raise_error
- expect { @resource.static "yep" }.to raise_error(ArgumentError)
+ expect { resource.static true }.not_to raise_error
+ expect { resource.static false }.not_to raise_error
+ expect { resource.static "yep" }.to raise_error(ArgumentError)
end
it "accepts the content property" do
- expect { @resource.content nil }.not_to raise_error
- expect { @resource.content "test" }.not_to raise_error
- expect { @resource.content({}) }.not_to raise_error
- expect { @resource.content 5 }.to raise_error(ArgumentError)
+ expect { resource.content nil }.not_to raise_error
+ expect { resource.content "test" }.not_to raise_error
+ expect { resource.content({}) }.not_to raise_error
+ expect { resource.content 5 }.to raise_error(ArgumentError)
end
it "accepts the user property" do
- expect { @resource.user nil }.not_to raise_error
- expect { @resource.user "deploy" }.not_to raise_error
- expect { @resource.user 5 }.to raise_error(ArgumentError)
+ expect { resource.user nil }.not_to raise_error
+ expect { resource.user "deploy" }.not_to raise_error
+ expect { resource.user 5 }.to raise_error(ArgumentError)
end
it "accepts the triggers_reload property" do
- expect { @resource.triggers_reload true }.not_to raise_error
- expect { @resource.triggers_reload false }.not_to raise_error
- expect { @resource.triggers_reload "no" }.to raise_error(ArgumentError)
+ expect { resource.triggers_reload true }.not_to raise_error
+ expect { resource.triggers_reload false }.not_to raise_error
+ expect { resource.triggers_reload "no" }.to raise_error(ArgumentError)
end
it "reports its state" do
- @resource.active true
- @resource.enabled true
- @resource.masked false
- @resource.static false
- @resource.content "test"
- state = @resource.state_for_resource_reporter
+ resource.active true
+ resource.enabled true
+ resource.masked false
+ resource.static false
+ resource.content "test"
+ state = resource.state_for_resource_reporter
expect(state[:active]).to eq(true)
expect(state[:enabled]).to eq(true)
expect(state[:masked]).to eq(false)
@@ -118,16 +112,16 @@ describe Chef::Resource::SystemdUnit do
end
it "returns the unit name as its identity" do
- expect(@resource.identity).to eq("sysstat-collect.timer")
+ expect(resource.identity).to eq("sysstat-collect.timer")
end
it "serializes to ini with a string-formatted content property" do
- @resource.content(unit_content_string)
- expect(@resource.to_ini).to eq unit_content_string
+ resource.content(unit_content_string)
+ expect(resource.to_ini).to eq unit_content_string
end
it "serializes to ini with a hash-formatted content property" do
- @resource.content(unit_content_hash)
- expect(@resource.to_ini).to eq unit_content_string
+ resource.content(unit_content_hash)
+ expect(resource.to_ini).to eq unit_content_string
end
end
diff --git a/spec/unit/resource/template_spec.rb b/spec/unit/resource/template_spec.rb
index 966a86ba6b..14e48900d3 100644
--- a/spec/unit/resource/template_spec.rb
+++ b/spec/unit/resource/template_spec.rb
@@ -19,76 +19,71 @@
require "spec_helper"
describe Chef::Resource::Template do
-
- before(:each) do
- @resource = Chef::Resource::Template.new("fakey_fakerton")
- end
+ let(:resource) { Chef::Resource::Template.new("fakey_fakerton") }
describe "initialize" do
- it "should create a new Chef::Resource::Template" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::File)
- expect(@resource).to be_a_kind_of(Chef::Resource::Template)
+ it "is a subclass of Chef::Resource::File" do
+ expect(resource).to be_a_kind_of(Chef::Resource::File)
end
end
describe "source" do
- it "should accept a string for the template source" do
- @resource.source "something"
- expect(@resource.source).to eql("something")
+ it "accepts a string for the template source" do
+ resource.source "something"
+ expect(resource.source).to eql("something")
end
- it "should have a default based on the param name with .erb appended" do
- expect(@resource.source).to eql("fakey_fakerton.erb")
+ it "has a default based on the param name with .erb appended" do
+ expect(resource.source).to eql("fakey_fakerton.erb")
end
- it "should use only the basename of the file as the default" do
+ it "uses only the basename of the file as the default" do
r = Chef::Resource::Template.new("/tmp/obit/fakey_fakerton")
expect(r.source).to eql("fakey_fakerton.erb")
end
end
describe "variables" do
- it "should accept a hash for the variable list" do
- @resource.variables({ :reluctance => :awkward })
- expect(@resource.variables).to eq({ :reluctance => :awkward })
+ it "accepts a hash for the variable list" do
+ resource.variables({ :reluctance => :awkward })
+ expect(resource.variables).to eq({ :reluctance => :awkward })
end
end
describe "cookbook" do
- it "should accept a string for the cookbook name" do
- @resource.cookbook("foo")
- expect(@resource.cookbook).to eq("foo")
+ it "accepts a string for the cookbook name" do
+ resource.cookbook("foo")
+ expect(resource.cookbook).to eq("foo")
end
- it "should default to nil" do
- expect(@resource.cookbook).to eq(nil)
+ it "defaults to nil" do
+ expect(resource.cookbook).to eq(nil)
end
end
describe "local" do
- it "should accept a boolean for whether a template is local or remote" do
- @resource.local(true)
- expect(@resource.local).to eq(true)
+ it "accepts a boolean for whether a template is local or remote" do
+ resource.local(true)
+ expect(resource.local).to eq(true)
end
- it "should default to false" do
- expect(@resource.local).to eq(false)
+ it "defaults to false" do
+ expect(resource.local).to eq(false)
end
end
describe "when it has a path, owner, group, mode, and checksum" do
before do
- @resource.path("/tmp/foo.txt")
- @resource.owner("root")
- @resource.group("wheel")
- @resource.mode("0644")
- @resource.checksum("1" * 64)
+ resource.path("/tmp/foo.txt")
+ resource.owner("root")
+ resource.group("wheel")
+ resource.mode("0644")
+ resource.checksum("1" * 64)
end
context "on unix", :unix_only do
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:owner]).to eq("root")
expect(state[:group]).to eq("wheel")
expect(state[:mode]).to eq("0644")
@@ -102,7 +97,7 @@ describe Chef::Resource::Template do
end
it "returns the file path as its identity" do
- expect(@resource.identity).to eq("/tmp/foo.txt")
+ expect(resource.identity).to eq("/tmp/foo.txt")
end
end
@@ -115,16 +110,16 @@ describe Chef::Resource::Template do
end
it "collects helper method bodies as blocks" do
- @resource.helper(:example_1) { "example_1" }
- @resource.helper(:example_2) { "example_2" }
- expect(@resource.inline_helper_blocks[:example_1].call).to eq("example_1")
- expect(@resource.inline_helper_blocks[:example_2].call).to eq("example_2")
+ resource.helper(:example_1) { "example_1" }
+ resource.helper(:example_2) { "example_2" }
+ expect(resource.inline_helper_blocks[:example_1].call).to eq("example_1")
+ expect(resource.inline_helper_blocks[:example_2].call).to eq("example_2")
end
it "compiles helper methods into a module" do
- @resource.helper(:example_1) { "example_1" }
- @resource.helper(:example_2) { "example_2" }
- modules = @resource.helper_modules
+ resource.helper(:example_1) { "example_1" }
+ resource.helper(:example_2) { "example_2" }
+ modules = resource.helper_modules
expect(modules.size).to eq(1)
o = Object.new
modules.each { |m| o.extend(m) }
@@ -133,38 +128,38 @@ describe Chef::Resource::Template do
end
it "compiles helper methods with arguments into a module" do
- @resource.helper(:shout) { |quiet| quiet.upcase }
- modules = @resource.helper_modules
+ resource.helper(:shout) { |quiet| quiet.upcase }
+ modules = resource.helper_modules
o = Object.new
modules.each { |m| o.extend(m) }
expect(o.shout("shout")).to eq("SHOUT")
end
it "raises an error when attempting to define a helper method without a method body" do
- expect { @resource.helper(:example) }.to raise_error(Chef::Exceptions::ValidationFailed)
+ expect { resource.helper(:example) }.to raise_error(Chef::Exceptions::ValidationFailed)
end
it "raises an error when attempting to define a helper method with a non-Symbod method name" do
- expect { @resource.helper("example") { "fail" } }.to raise_error(Chef::Exceptions::ValidationFailed)
+ expect { resource.helper("example") { "fail" } }.to raise_error(Chef::Exceptions::ValidationFailed)
end
it "collects helper module bodies as blocks" do
- @resource.helpers do
+ resource.helpers do
def example_1
"example_1"
end
end
- module_body = @resource.inline_helper_modules.first
+ module_body = resource.inline_helper_modules.first
expect(module_body).to be_a(Proc)
end
it "compiles helper module bodies into modules" do
- @resource.helpers do
+ resource.helpers do
def example_1
"example_1"
end
end
- modules = @resource.helper_modules
+ modules = resource.helper_modules
expect(modules.size).to eq(1)
o = Object.new
modules.each { |m| o.extend(m) }
@@ -172,39 +167,37 @@ describe Chef::Resource::Template do
end
it "raises an error when no block or module name is given for helpers definition" do
- expect { @resource.helpers() }.to raise_error(Chef::Exceptions::ValidationFailed)
+ expect { resource.helpers() }.to raise_error(Chef::Exceptions::ValidationFailed)
end
it "raises an error when a non-module is given for helpers definition" do
- expect { @resource.helpers("NotAModule") }.to raise_error(Chef::Exceptions::ValidationFailed)
+ expect { resource.helpers("NotAModule") }.to raise_error(Chef::Exceptions::ValidationFailed)
end
it "raises an error when a module name and block are both given for helpers definition" do
- expect { @resource.helpers(ExampleHelpers) { module_code } }.to raise_error(Chef::Exceptions::ValidationFailed)
+ expect { resource.helpers(ExampleHelpers) { module_code } }.to raise_error(Chef::Exceptions::ValidationFailed)
end
it "collects helper modules" do
- @resource.helpers(ExampleHelpers)
- expect(@resource.helper_modules).to include(ExampleHelpers)
+ resource.helpers(ExampleHelpers)
+ expect(resource.helper_modules).to include(ExampleHelpers)
end
it "combines all helpers into a set of compiled modules" do
- @resource.helpers(ExampleHelpers)
- @resource.helpers do
+ resource.helpers(ExampleHelpers)
+ resource.helpers do
def inline_module
"inline_module"
end
end
- @resource.helper(:inline_method) { "inline_method" }
- expect(@resource.helper_modules.size).to eq(3)
+ resource.helper(:inline_method) { "inline_method" }
+ expect(resource.helper_modules.size).to eq(3)
o = Object.new
- @resource.helper_modules.each { |m| o.extend(m) }
+ resource.helper_modules.each { |m| o.extend(m) }
expect(o.static_example).to eq("static_example")
expect(o.inline_module).to eq("inline_module")
expect(o.inline_method).to eq("inline_method")
end
-
end
-
end
diff --git a/spec/unit/resource/user_spec.rb b/spec/unit/resource/user_spec.rb
index 1a3f0284e3..1c583afc44 100644
--- a/spec/unit/resource/user_spec.rb
+++ b/spec/unit/resource/user_spec.rb
@@ -19,115 +19,104 @@
require "spec_helper"
describe Chef::Resource::User, "initialize" do
- before(:each) do
- @resource = Chef::Resource::User.new("adam")
- end
-
- it "should create a new Chef::Resource::User" do
- expect(@resource).to be_a_kind_of(Chef::Resource)
- expect(@resource).to be_a_kind_of(Chef::Resource::User)
- end
+ let(:resource) { Chef::Resource::User.new("adam") }
- it "should set the resource_name to :user" do
- expect(@resource.resource_name).to eql(:user_resource_abstract_base_class)
+ it "sets the resource_name to :user" do
+ expect(resource.resource_name).to eql(:user_resource_abstract_base_class)
end
- it "should set the username equal to the argument to initialize" do
- expect(@resource.username).to eql("adam")
+ it "sets the username equal to the argument to initialize" do
+ expect(resource.username).to eql("adam")
end
%w{comment uid gid home shell password}.each do |attrib|
- it "should set #{attrib} to nil" do
- expect(@resource.send(attrib)).to eql(nil)
+ it "sets #{attrib} to nil" do
+ expect(resource.send(attrib)).to eql(nil)
end
end
- it "should set action to :create" do
- expect(@resource.action).to eql([:create])
+ it "sets action to :create" do
+ expect(resource.action).to eql([:create])
end
- it "should set manage_home to false" do
- expect(@resource.manage_home).to eql(false)
+ it "sets manage_home to false" do
+ expect(resource.manage_home).to eql(false)
end
- it "should set non_unique to false" do
- expect(@resource.non_unique).to eql(false)
+ it "sets non_unique to false" do
+ expect(resource.non_unique).to eql(false)
end
- it "should set force to false" do
- expect(@resource.force).to eql(false)
+ it "sets force to false" do
+ expect(resource.force).to eql(false)
end
%w{create remove modify manage lock unlock}.each do |action|
- it "should allow action #{action}" do
- expect(@resource.allowed_actions.detect { |a| a == action.to_sym }).to eql(action.to_sym)
+ it "allows action #{action}" do
+ expect(resource.allowed_actions.detect { |a| a == action.to_sym }).to eql(action.to_sym)
end
end
- it "should accept domain users (@ or \ separator) on non-windows" do
- expect { @resource.username "domain\@user" }.not_to raise_error
- expect(@resource.username).to eq("domain\@user")
- expect { @resource.username "domain\\user" }.not_to raise_error
- expect(@resource.username).to eq("domain\\user")
+ it "accepts domain users (@ or \ separator) on non-windows" do
+ expect { resource.username "domain\@user" }.not_to raise_error
+ expect(resource.username).to eq("domain\@user")
+ expect { resource.username "domain\\user" }.not_to raise_error
+ expect(resource.username).to eq("domain\\user")
end
end
%w{username comment home shell password}.each do |attrib|
describe Chef::Resource::User, attrib do
- before(:each) do
- @resource = Chef::Resource::User.new("adam")
- end
+ let(:resource) { Chef::Resource::User.new("adam") }
- it "should allow a string" do
- @resource.send(attrib, "adam")
- expect(@resource.send(attrib)).to eql("adam")
+ it "allows a string" do
+ resource.send(attrib, "adam")
+ expect(resource.send(attrib)).to eql("adam")
end
- it "should not allow a hash" do
- expect { @resource.send(attrib, { :woot => "i found it" }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.send(attrib, { :woot => "i found it" }) }.to raise_error(ArgumentError)
end
end
end
%w{uid gid}.each do |attrib|
describe Chef::Resource::User, attrib do
- before(:each) do
- @resource = Chef::Resource::User.new("adam")
- end
+ let(:resource) { Chef::Resource::User.new("adam") }
- it "should allow a string" do
- @resource.send(attrib, "100")
- expect(@resource.send(attrib)).to eql("100")
+ it "allows a string" do
+ resource.send(attrib, "100")
+ expect(resource.send(attrib)).to eql("100")
end
- it "should allow an integer" do
- @resource.send(attrib, 100)
- expect(@resource.send(attrib)).to eql(100)
+ it "allows an integer" do
+ resource.send(attrib, 100)
+ expect(resource.send(attrib)).to eql(100)
end
- it "should not allow a hash" do
- expect { @resource.send(attrib, { :woot => "i found it" }) }.to raise_error(ArgumentError)
+ it "does not allow a hash" do
+ expect { resource.send(attrib, { :woot => "i found it" }) }.to raise_error(ArgumentError)
end
end
describe "when it has uid, gid, and home" do
+ let(:resource) { Chef::Resource::User.new("root") }
+
before do
- @resource = Chef::Resource::User.new("root")
- @resource.uid(123)
- @resource.gid(456)
- @resource.home("/usr/local/root/")
+ resource.uid(123)
+ resource.gid(456)
+ resource.home("/usr/local/root/")
end
it "describes its state" do
- state = @resource.state_for_resource_reporter
+ state = resource.state_for_resource_reporter
expect(state[:uid]).to eq(123)
expect(state[:gid]).to eq(456)
expect(state[:home]).to eq("/usr/local/root/")
end
it "returns the username as its identity" do
- expect(@resource.identity).to eq("root")
+ expect(resource.identity).to eq("root")
end
end
-
end
diff --git a/spec/unit/resource/windows_package_spec.rb b/spec/unit/resource/windows_package_spec.rb
index 5aa3707199..bb4052f8e3 100644
--- a/spec/unit/resource/windows_package_spec.rb
+++ b/spec/unit/resource/windows_package_spec.rb
@@ -33,8 +33,8 @@ describe Chef::Resource::WindowsPackage, "initialize" do
let(:resource) { Chef::Resource::WindowsPackage.new("solitaire.msi") }
- it "returns a Chef::Resource::WindowsPackage" do
- expect(resource).to be_a_kind_of(Chef::Resource::WindowsPackage)
+ it "is a subclass of Chef::Resource::Package" do
+ expect(resource).to be_a_kind_of(Chef::Resource::Package)
end
it "sets the resource_name to :windows_package" do
@@ -88,7 +88,7 @@ describe Chef::Resource::WindowsPackage, "initialize" do
let(:resource_source) { "https://foo.bar/solitare.msi" }
let(:resource) { Chef::Resource::WindowsPackage.new(resource_source) }
- it "should return the source unmodified" do
+ it "returns the source unmodified" do
expect(resource.source).to eq(resource_source)
end
end
diff --git a/spec/unit/resource/windows_path_spec.rb b/spec/unit/resource/windows_path_spec.rb
index aecea8ee6b..8f29a11e4e 100644
--- a/spec/unit/resource/windows_path_spec.rb
+++ b/spec/unit/resource/windows_path_spec.rb
@@ -19,20 +19,23 @@
require "spec_helper"
describe Chef::Resource::WindowsPath do
- subject { Chef::Resource::WindowsPath.new("some_path") }
-
- it { is_expected.to be_a_kind_of(Chef::Resource) }
- it { is_expected.to be_a_instance_of(Chef::Resource::WindowsPath) }
+ let(:resource) { Chef::Resource::WindowsPath.new("some_path") }
it "sets resource name as :windows_path" do
- expect(subject.resource_name).to eql(:windows_path)
+ expect(resource.resource_name).to eql(:windows_path)
end
- it "sets the path as it's name" do
- expect(subject.path).to eql("some_path")
+ it "sets the path as its name" do
+ expect(resource.path).to eql("some_path")
end
it "sets the default action as :add" do
- expect(subject.action).to eql(:add)
+ expect(resource.action).to eql([:add])
+ end
+
+ it "supports :add and :remove actions" do
+ expect { resource.action :add }.not_to raise_error
+ expect { resource.action :remove }.not_to raise_error
+ expect { resource.action :delete }.to raise_error(ArgumentError)
end
end
diff --git a/spec/unit/resource/windows_service_spec.rb b/spec/unit/resource/windows_service_spec.rb
index 2455a70f02..f5de5b6965 100644
--- a/spec/unit/resource/windows_service_spec.rb
+++ b/spec/unit/resource/windows_service_spec.rb
@@ -29,10 +29,6 @@ describe Chef::Resource::WindowsService, "initialize" do
let(:resource) { Chef::Resource::WindowsService.new("BITS") }
- it "returns a Chef::Resource::WindowsService" do
- expect(resource).to be_a_kind_of(Chef::Resource::WindowsService)
- end
-
it "sets the resource_name to :windows_service" do
expect(resource.resource_name).to eql(:windows_service)
end
@@ -46,4 +42,29 @@ describe Chef::Resource::WindowsService, "initialize" do
resource.action :configure_startup
expect(resource.action).to eq([:configure_startup])
end
+
+ # Attributes that are Strings
+ %i{description service_name binary_path_name load_order_group dependencies
+ run_as_user run_as_password display_name}.each do |prop|
+ it "support setting #{prop}" do
+ resource.send("#{prop}=", "some value")
+ expect(resource.send(prop)).to eq("some value")
+ end
+ end
+
+ # Attributes that are Integers
+ %i{desired_access error_control service_type}.each do |prop|
+ it "support setting #{prop}" do
+ resource.send("#{prop}=", 1)
+ expect(resource.send(prop)).to eq(1)
+ end
+ end
+
+ # Attributes that are Booleans
+ %i{delayed_start}.each do |prop|
+ it "support setting #{prop}" do
+ resource.send("#{prop}=", true)
+ expect(resource.send(prop)).to eq(true)
+ end
+ end
end
diff --git a/spec/unit/resource/windows_task_spec.rb b/spec/unit/resource/windows_task_spec.rb
index 2b3ee16024..4b74a4f78a 100644
--- a/spec/unit/resource/windows_task_spec.rb
+++ b/spec/unit/resource/windows_task_spec.rb
@@ -21,21 +21,16 @@ require "spec_helper"
describe Chef::Resource::WindowsTask do
let(:resource) { Chef::Resource::WindowsTask.new("sample_task") }
- it "creates a new Chef::Resource::WindowsTask" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_instance_of(Chef::Resource::WindowsTask)
- end
-
it "sets resource name as :windows_task" do
expect(resource.resource_name).to eql(:windows_task)
end
- it "sets the task_name as it's name" do
+ it "sets the task_name as its name" do
expect(resource.task_name).to eql("sample_task")
end
it "sets the default action as :create" do
- expect(resource.action).to eql(:create)
+ expect(resource.action).to eql([:create])
end
it "sets the default user as System" do
@@ -62,39 +57,86 @@ describe Chef::Resource::WindowsTask do
expect(resource.frequency).to eql(:hourly)
end
+ context "when user is set but password is not" do
+ it "raises an error if the user is a non-system user" do
+ resource.user "bob"
+ expect { resource.after_created }.to raise_error(ArgumentError, %q{Cannot specify a user other than the system users without specifying a password!. Valid passwordless users: 'NT AUTHORITY\SYSTEM', 'SYSTEM', 'NT AUTHORITY\LOCALSERVICE', 'NT AUTHORITY\NETWORKSERVICE', 'BUILTIN\USERS', 'USERS'})
+ end
+
+ it "does not raise an error if the user is a system user" do
+ resource.user 'NT AUTHORITY\SYSTEM'
+ expect { resource.after_created }.to_not raise_error
+ end
+
+ it "does not raise an error if the user is a system user even if lowercase" do
+ resource.user 'nt authority\system'
+ expect { resource.after_created }.to_not raise_error
+ end
+ end
+
context "when random_delay is passed" do
it "raises error if frequency is `:once`" do
resource.frequency :once
resource.random_delay "20"
- expect { resource.after_created }.to raise_error(Chef::Exceptions::ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
+ expect { resource.after_created }.to raise_error(ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
end
it "raises error for invalid random_delay" do
resource.frequency :monthly
resource.random_delay "xyz"
- expect { resource.after_created }.to raise_error(Chef::Exceptions::ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as a String e.g. '60'.")
+ expect { resource.after_created }.to raise_error(ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
+ end
+
+ it "raises error for invalid random_delay which looks like an Integer" do
+ resource.frequency :monthly
+ resource.random_delay "5,000"
+ expect { resource.after_created }.to raise_error(ArgumentError, "Invalid value passed for `random_delay`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
end
- it "converts seconds into iso8601 format" do
+ it "converts seconds String into iso8601 duration format" do
resource.frequency :monthly
resource.random_delay "60"
resource.after_created
expect(resource.random_delay).to eq("PT60S")
end
+
+ it "converts seconds Integer into iso8601 duration format" do
+ resource.frequency :monthly
+ resource.random_delay 60
+ resource.after_created
+ expect(resource.random_delay).to eq("PT60S")
+ end
+
+ it "raises error that random_delay is not supported" do
+ expect { resource.send(:validate_random_delay, 60, :on_idle) }.to raise_error(ArgumentError, "`random_delay` property is supported only for frequency :minute, :hourly, :daily, :weekly and :monthly")
+ end
end
- context "when execution_time_limit is passed" do
- it "sets the deafult value as PT72H" do
+ context "when execution_time_limit isn't specified" do
+ it "sets the default value to PT72H" do
resource.after_created
expect(resource.execution_time_limit).to eq("PT72H")
end
+ end
+ context "when execution_time_limit is passed" do
it "raises error for invalid execution_time_limit" do
resource.execution_time_limit "abc"
- expect { resource.after_created }.to raise_error(Chef::Exceptions::ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as a String e.g. '60'.")
+ expect { resource.after_created }.to raise_error(ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
+ end
+
+ it "raises error for invalid execution_time_limit that looks like an Integer" do
+ resource.execution_time_limit "5,000"
+ expect { resource.after_created }.to raise_error(ArgumentError, "Invalid value passed for `execution_time_limit`. Please pass seconds as an Integer (e.g. 60) or a String with numeric values only (e.g. '60').")
end
- it "converts seconds into iso8601 format" do
+ it "converts seconds Integer into iso8601 format" do
+ resource.execution_time_limit 60
+ resource.after_created
+ expect(resource.execution_time_limit).to eq("PT60S")
+ end
+
+ it "converts seconds String into iso8601 format" do
resource.execution_time_limit "60"
resource.after_created
expect(resource.execution_time_limit).to eq("PT60S")
@@ -102,24 +144,50 @@ describe Chef::Resource::WindowsTask do
end
context "#validate_start_time" do
- it "raises error if start_time is nil" do
- expect { resource.send(:validate_start_time, nil) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_time` needs to be provided with `frequency :once`")
+ it "raises error if start_time is nil when frequency `:once`" do
+ resource.frequency :once
+ expect { resource.send(:validate_start_time, nil, :once) }.to raise_error(ArgumentError, "`start_time` needs to be provided with `frequency :once`")
+ end
+
+ it "raises error if start_time is given when frequency `:none`" do
+ resource.frequency :none
+ expect { resource.send(:validate_start_time, "12.00", :none) }.to raise_error(ArgumentError, "`start_time` property is not supported with `frequency :none`")
+ end
+
+ it "raises error if start_time is not HH:mm format" do
+ resource.frequency :once
+ expect { resource.send(:validate_start_time, "2:30", :once) }.to raise_error(ArgumentError, "`start_time` property must be in the HH:mm format (e.g. 6:20pm -> 18:20).")
+ end
+
+ it "does not raise error if start_time is in HH:mm format" do
+ resource.frequency :once
+ expect { resource.send(:validate_start_time, "12:30", :once) }.not_to raise_error
end
end
context "#validate_start_day" do
- it "raise error if start_day is passed with frequency :on_logon" do
- resource.frequency :on_logon
- expect { resource.send(:validate_start_day, "Wed", :on_logon) }.to raise_error(Chef::Exceptions::ArgumentError, "`start_day` property is not supported with frequency: on_logon")
+ it "raise error if start_day is passed with invalid frequency (:on_logon)" do
+ expect { resource.send(:validate_start_day, "02/07/1984", :on_logon) }.to raise_error(ArgumentError, "`start_day` property is not supported with frequency: on_logon")
end
- end
- context "#validate_user_and_password" do
- context "when password is not passed" do
- it "raises error with non-system users" do
- allow(resource).to receive(:use_password?).and_return(true)
- expect { resource.send(:validate_user_and_password, "Testuser", nil) }.to raise_error("Can't specify a non-system user without a password!")
- end
+ it "does not raise error if start_day is passed with valid frequency (:weekly)" do
+ expect { resource.send(:validate_start_day, "02/07/1984", :weekly) }.not_to raise_error
+ end
+
+ it "raise error if start_day is passed with invalid date format (DD/MM/YYYY)" do
+ expect { resource.send(:validate_start_day, "28/12/2009", :weekly) }.to raise_error(ArgumentError, "`start_day` property must be in the MM/DD/YYYY format.")
+ end
+
+ it "raise error if start_day is passed with invalid date format (M/DD/YYYY)" do
+ expect { resource.send(:validate_start_day, "2/07/1984", :weekly) }.to raise_error(ArgumentError, "`start_day` property must be in the MM/DD/YYYY format.")
+ end
+
+ it "raise error if start_day is passed with invalid date format (MM/D/YYYY)" do
+ expect { resource.send(:validate_start_day, "02/7/1984", :weekly) }.to raise_error(ArgumentError, "`start_day` property must be in the MM/DD/YYYY format.")
+ end
+
+ it "raise error if start_day is passed with invalid date format (MM/DD/YY)" do
+ expect { resource.send(:validate_start_day, "02/07/84", :weekly) }.to raise_error(ArgumentError, "`start_day` property must be in the MM/DD/YYYY format.")
end
end
@@ -132,42 +200,42 @@ describe Chef::Resource::WindowsTask do
context "#validate_create_frequency_modifier" do
context "when frequency is :minute" do
it "raises error if frequency_modifier > 1439" do
- expect { resource.send(:validate_create_frequency_modifier, :minute, 1500) }.to raise_error("frequency_modifier value 1500 is invalid. Valid values for :minute frequency are 1 - 1439.")
+ expect { resource.send(:validate_create_frequency_modifier, :minute, 1500) }.to raise_error("frequency_modifier value 1500 is invalid. Valid values for :minute frequency are 1 - 1439.")
end
end
context "when frequency is :hourly" do
it "raises error if frequency_modifier > 23" do
- expect { resource.send(:validate_create_frequency_modifier, :hourly, 24) }.to raise_error("frequency_modifier value 24 is invalid. Valid values for :hourly frequency are 1 - 23.")
+ expect { resource.send(:validate_create_frequency_modifier, :hourly, 24) }.to raise_error("frequency_modifier value 24 is invalid. Valid values for :hourly frequency are 1 - 23.")
end
end
context "when frequency is :daily" do
it "raises error if frequency_modifier > 365" do
- expect { resource.send(:validate_create_frequency_modifier, :daily, 366) }.to raise_error("frequency_modifier value 366 is invalid. Valid values for :daily frequency are 1 - 365.")
+ expect { resource.send(:validate_create_frequency_modifier, :daily, 366) }.to raise_error("frequency_modifier value 366 is invalid. Valid values for :daily frequency are 1 - 365.")
end
end
context "when frequency is :weekly" do
it "raises error if frequency_modifier > 52" do
- expect { resource.send(:validate_create_frequency_modifier, :weekly, 53) }.to raise_error("frequency_modifier value 53 is invalid. Valid values for :weekly frequency are 1 - 52.")
+ expect { resource.send(:validate_create_frequency_modifier, :weekly, 53) }.to raise_error("frequency_modifier value 53 is invalid. Valid values for :weekly frequency are 1 - 52.")
end
end
context "when frequency is :monthly" do
it "raises error if frequency_modifier > 12" do
- expect { resource.send(:validate_create_frequency_modifier, :monthly, 14) }.to raise_error("frequency_modifier value 14 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
+ expect { resource.send(:validate_create_frequency_modifier, :monthly, 14) }.to raise_error("frequency_modifier value 14 is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
end
it "raises error if frequency_modifier is invalid" do
- expect { resource.send(:validate_create_frequency_modifier, :monthly, "abc") }.to raise_error("frequency_modifier value abc is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
+ expect { resource.send(:validate_create_frequency_modifier, :monthly, "abc") }.to raise_error("frequency_modifier value abc is invalid. Valid values for :monthly frequency are 1 - 12, 'FIRST', 'SECOND', 'THIRD', 'FOURTH', 'LAST', 'LASTDAY'.")
end
end
end
context "#validate_create_day" do
it "raises error if frequency is not :weekly or :monthly" do
- expect { resource.send(:validate_create_day, "Mon", :once) }.to raise_error("day attribute is only valid for tasks that run monthly or weekly")
+ expect { resource.send(:validate_create_day, "Mon", :once) }.to raise_error("day property is only valid for tasks that run monthly or weekly")
end
it "accepts a valid single day" do
@@ -179,13 +247,13 @@ describe Chef::Resource::WindowsTask do
end
it "raises error for invalid day value" do
- expect { resource.send(:validate_create_day, "xyz", :weekly) }.to raise_error("day attribute invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma.")
+ expect { resource.send(:validate_create_day, "xyz", :weekly) }.to raise_error(ArgumentError, "day property invalid. Only valid values are: MON, TUE, WED, THU, FRI, SAT, SUN and *. Multiple values must be separated by a comma.")
end
end
context "#validate_create_months" do
it "raises error if frequency is not :monthly" do
- expect { resource.send(:validate_create_months, "Jan", :once) }.to raise_error("months attribute is only valid for tasks that run monthly")
+ expect { resource.send(:validate_create_months, "Jan", :once) }.to raise_error(ArgumentError, "months property is only valid for tasks that run monthly")
end
it "accepts a valid single month" do
@@ -197,17 +265,54 @@ describe Chef::Resource::WindowsTask do
end
it "raises error for invalid month value" do
- expect { resource.send(:validate_create_months, "xyz", :monthly) }.to raise_error("months attribute invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
+ expect { resource.send(:validate_create_months, "xyz", :monthly) }.to raise_error(ArgumentError, "months property invalid. Only valid values are: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC and *. Multiple values must be separated by a comma.")
end
end
context "#validate_idle_time" do
it "raises error if frequency is not :on_idle" do
- expect { resource.send(:validate_idle_time, 5, :hourly) }.to raise_error("idle_time attribute is only valid for tasks that run on_idle")
+ [:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :none].each do |frequency|
+ expect { resource.send(:validate_idle_time, 5, frequency) }.to raise_error(ArgumentError, "idle_time property is only valid for tasks that run on_idle")
+ end
end
it "raises error if idle_time > 999" do
- expect { resource.send(:validate_idle_time, 1000, :on_idle) }.to raise_error("idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ expect { resource.send(:validate_idle_time, 1000, :on_idle) }.to raise_error(ArgumentError, "idle_time value 1000 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ end
+
+ it "raises error if idle_time < 0" do
+ expect { resource.send(:validate_idle_time, -5, :on_idle) }.to raise_error(ArgumentError, "idle_time value -5 is invalid. Valid values for :on_idle frequency are 1 - 999.")
+ end
+
+ it "raises error if idle_time is not set" do
+ expect { resource.send(:validate_idle_time, nil, :on_idle) }.to raise_error(ArgumentError, "idle_time value should be set for :on_idle frequency.")
+ end
+
+ it "does not raises error if idle_time is not set for other frequencies" do
+ [:minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :none].each do |frequency|
+ expect { resource.send(:validate_idle_time, nil, frequency) }.not_to raise_error
+ end
+ end
+ end
+
+ context "#sec_to_dur" do
+ it "return nil when passed 0" do
+ expect(resource.send(:sec_to_dur, 0)).to eql("PT0S")
+ end
+ it "return PT1S when passed 1" do
+ expect(resource.send(:sec_to_dur, 1)).to eql("PT1S")
+ end
+ it "return PT86400S when passed 86400" do
+ expect(resource.send(:sec_to_dur, 86400)).to eql("PT86400S")
+ end
+ it "return PT86401S when passed 86401" do
+ expect(resource.send(:sec_to_dur, 86401)).to eql("PT86401S")
+ end
+ it "return PT86500S when passed 86500" do
+ expect(resource.send(:sec_to_dur, 86500)).to eql("PT86500S")
+ end
+ it "return PT604801S when passed 604801" do
+ expect(resource.send(:sec_to_dur, 604801)).to eql("PT604801S")
end
end
end
diff --git a/spec/unit/resource/yum_package_spec.rb b/spec/unit/resource/yum_package_spec.rb
index a1e8417e0e..ce289ce45a 100644
--- a/spec/unit/resource/yum_package_spec.rb
+++ b/spec/unit/resource/yum_package_spec.rb
@@ -78,7 +78,7 @@ describe Chef::Resource::YumPackage, "arch" do
@resource = Chef::Resource::YumPackage.new("foo")
end
- it "should set the arch variable to whatever is passed in" do
+ it "sets the arch variable to whatever is passed in" do
@resource.arch("i386")
expect(@resource.arch).to eql("i386")
end
diff --git a/spec/unit/resource/yum_repository_spec.rb b/spec/unit/resource/yum_repository_spec.rb
index afd6c6739a..3ff9b85f88 100644
--- a/spec/unit/resource/yum_repository_spec.rb
+++ b/spec/unit/resource/yum_repository_spec.rb
@@ -24,25 +24,78 @@ describe Chef::Resource::YumRepository do
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:resource) { Chef::Resource::YumRepository.new("multiverse", run_context) }
- context "on linux", :linux_only do
- it "should create a new Chef::Resource::YumRepository" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::YumRepository)
- end
+ it "has a resource_name of :yum_repository" do
+ expect(resource.resource_name).to eq(:yum_repository)
+ end
+
+ it "the repositoryid property is the name_property" do
+ expect(resource.repositoryid).to eq("multiverse")
+ end
+
+ it "the timeout property expects numeric Strings" do
+ expect { resource.timeout "123" }.not_to raise_error(ArgumentError)
+ expect { resource.timeout "123foo" }.to raise_error(ArgumentError)
+ end
+
+ it "the priority property expects numeric Strings from '1' to '99'" do
+ expect { resource.priority "99" }.not_to raise_error(ArgumentError)
+ expect { resource.priority "1" }.not_to raise_error(ArgumentError)
+ expect { resource.priority "100" }.to raise_error(ArgumentError)
+ expect { resource.priority "0" }.to raise_error(ArgumentError)
+ end
+
+ it "the failovermethod property accepts 'priority' or 'roundrobin'" do
+ expect { resource.failovermethod "priority" }.not_to raise_error(ArgumentError)
+ expect { resource.failovermethod "roundrobin" }.not_to raise_error(ArgumentError)
+ expect { resource.failovermethod "bob" }.to raise_error(ArgumentError)
+ end
+
+ it "the http_caching property accepts 'packages', 'all', or 'none'" do
+ expect { resource.http_caching "packages" }.not_to raise_error(ArgumentError)
+ expect { resource.http_caching "all" }.not_to raise_error(ArgumentError)
+ expect { resource.http_caching "none" }.not_to raise_error(ArgumentError)
+ expect { resource.http_caching "bob" }.to raise_error(ArgumentError)
+ end
+
+ it "the metadata_expire property accepts a time value or 'never'" do
+ expect { resource.metadata_expire "100" }.not_to raise_error(ArgumentError)
+ expect { resource.metadata_expire "100d" }.not_to raise_error(ArgumentError)
+ expect { resource.metadata_expire "100h" }.not_to raise_error(ArgumentError)
+ expect { resource.metadata_expire "100m" }.not_to raise_error(ArgumentError)
+ expect { resource.metadata_expire "never" }.not_to raise_error(ArgumentError)
+ expect { resource.metadata_expire "100s" }.to raise_error(ArgumentError)
+ end
- it "should resolve to a Noop class when yum is not found" do
+ it "the mirror_expire property accepts a time value" do
+ expect { resource.mirror_expire "100" }.not_to raise_error(ArgumentError)
+ expect { resource.mirror_expire "100d" }.not_to raise_error(ArgumentError)
+ expect { resource.mirror_expire "100h" }.not_to raise_error(ArgumentError)
+ expect { resource.mirror_expire "100m" }.not_to raise_error(ArgumentError)
+ expect { resource.mirror_expire "never" }.to raise_error(ArgumentError)
+ end
+
+ it "the mirrorlist_expire property accepts a time value" do
+ expect { resource.mirrorlist_expire "100" }.not_to raise_error(ArgumentError)
+ expect { resource.mirrorlist_expire "100d" }.not_to raise_error(ArgumentError)
+ expect { resource.mirrorlist_expire "100h" }.not_to raise_error(ArgumentError)
+ expect { resource.mirrorlist_expire "100m" }.not_to raise_error(ArgumentError)
+ expect { resource.mirrorlist_expire "never" }.to raise_error(ArgumentError)
+ end
+
+ context "on linux", :linux_only do
+ it "resolves to a Noop class when yum is not found" do
expect(Chef::Provider::YumRepository).to receive(:which).with("yum").and_return(false)
expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
- it "should resolve to a YumRepository class when yum is found" do
+ it "resolves to a YumRepository class when yum is found" do
expect(Chef::Provider::YumRepository).to receive(:which).with("yum").and_return(true)
expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::YumRepository)
end
end
context "on windows", :windows_only do
- it "should resolve to a NoOp provider" do
+ it "resolves to a NoOp provider" do
expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
end
diff --git a/spec/unit/resource/zypper_repository_spec.rb b/spec/unit/resource/zypper_repository_spec.rb
index 16951d071c..889a1e1e9a 100644
--- a/spec/unit/resource/zypper_repository_spec.rb
+++ b/spec/unit/resource/zypper_repository_spec.rb
@@ -24,42 +24,43 @@ describe Chef::Resource::ZypperRepository do
let(:run_context) { Chef::RunContext.new(node, {}, events) }
let(:resource) { Chef::Resource::ZypperRepository.new("repo-source", run_context) }
- context "on linux", :linux_only do
- it "should create a new Chef::Resource::ZypperRepository" do
- expect(resource).to be_a_kind_of(Chef::Resource)
- expect(resource).to be_a_kind_of(Chef::Resource::ZypperRepository)
- end
+ it "has a resource_name of :zypper_repository" do
+ expect(resource.resource_name).to eq(:zypper_repository)
+ end
- it "should have a name of repo-source" do
- expect(resource.name).to eql("repo-source")
- end
+ it "repo_name is the name_property" do
+ expect(resource.repo_name).to eql("repo-source")
+ end
- it "should have a default action of create" do
- expect(resource.action).to eql([:create])
- end
+ it "has a default action of create" do
+ expect(resource.action).to eql([:create])
+ end
- it "supports all valid actions" do
- expect { resource.action :add }.not_to raise_error
- expect { resource.action :remove }.not_to raise_error
- expect { resource.action :create }.not_to raise_error
- expect { resource.action :refresh }.not_to raise_error
- expect { resource.action :delete }.to raise_error(ArgumentError)
- end
+ it "supports all valid actions" do
+ expect { resource.action :add }.not_to raise_error
+ expect { resource.action :remove }.not_to raise_error
+ expect { resource.action :create }.not_to raise_error
+ expect { resource.action :refresh }.not_to raise_error
+ expect { resource.action :delete }.to raise_error(ArgumentError)
+ end
- it "should resolve to a Noop class when zypper is not found" do
- expect(Chef::Provider::ZypperRepository).to receive(:which).with("zypper").and_return(false)
+ context "on linux", :linux_only do
+ it "resolves to a Noop class when on non-linux OS" do
+ node.automatic[:os] = "windows"
+ node.automatic[:platform_family] = "windows"
expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
- it "should resolve to a ZypperRepository class when zypper is found" do
- expect(Chef::Provider::ZypperRepository).to receive(:which).with("zypper").and_return(true)
- expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::ZypperRepository)
+ it "resolves to a Noop class when on non-suse linux" do
+ node.automatic[:os] = "linux"
+ node.automatic[:platform_family] = "debian"
+ expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::Noop)
end
- 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)
+ it "resolves to a ZypperRepository class when on a suse platform_family" do
+ node.automatic[:os] = "linux"
+ node.automatic[:platform_family] = "suse"
+ expect(resource.provider_for_action(:add)).to be_a(Chef::Provider::ZypperRepository)
end
end
end
diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb
index 9227c8b12d..fe853922a1 100644
--- a/spec/unit/resource_spec.rb
+++ b/spec/unit/resource_spec.rb
@@ -387,6 +387,37 @@ describe Chef::Resource do
end
end
+ context "Documentation of resources" do
+ it "can have a description" do
+ c = Class.new(Chef::Resource) do
+ description "my description"
+ end
+ expect(c.description).to eq "my description"
+ end
+
+ it "can say when it was introduced" do
+ c = Class.new(Chef::Resource) do
+ introduced "14.0"
+ end
+ expect(c.introduced).to eq "14.0"
+ end
+
+ it "can have some examples" do
+ c = Class.new(Chef::Resource) do
+ examples <<-EOH
+resource "foo" do
+ foo foo
+end
+ EOH
+ end
+ expect(c.examples).to eq <<-EOH
+resource "foo" do
+ foo foo
+end
+ EOH
+ 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
@@ -524,11 +555,6 @@ describe Chef::Resource do
resource.ignore_failure(true)
expect(resource.ignore_failure).to eq(true)
end
-
- it "should allow you to epic_fail" do
- resource.epic_fail(true)
- expect(resource.epic_fail).to eq(true)
- end
end
describe "retries" do
diff --git a/spec/unit/util/dsc/lcm_output_parser_spec.rb b/spec/unit/util/dsc/lcm_output_parser_spec.rb
index d59497de6f..65eaafe19c 100644
--- a/spec/unit/util/dsc/lcm_output_parser_spec.rb
+++ b/spec/unit/util/dsc/lcm_output_parser_spec.rb
@@ -19,20 +19,33 @@
require "chef/util/dsc/lcm_output_parser"
describe Chef::Util::DSC::LocalConfigurationManager::Parser do
- context "empty input parameter" do
+ context "empty input parameter for WhatIfParser" do
it "raises an exception when there are no valid lines" do
str = <<-EOF
EOF
- expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str) }.to raise_error(Chef::Exceptions::LCMParser)
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false) }.to raise_error(Chef::Exceptions::LCMParser)
end
it "raises an exception for a nil input" do
- expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(nil) }.to raise_error(Chef::Exceptions::LCMParser)
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(nil, false) }.to raise_error(Chef::Exceptions::LCMParser)
end
end
- context "correctly formatted output from lcm" do
+ context "empty input parameter for TestDSCParser" do
+ it "raises an exception when there are no valid lines" do
+ str = <<-EOF
+
+ EOF
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true) }.to raise_error(Chef::Exceptions::LCMParser)
+ end
+
+ it "raises an exception for a nil input" do
+ expect { Chef::Util::DSC::LocalConfigurationManager::Parser.parse(nil, true) }.to raise_error(Chef::Exceptions::LCMParser)
+ end
+ end
+
+ context "correctly formatted output from lcm for WhatIfParser" do
it "returns a single resource when only 1 logged with the correct name" do
str = <<EOF
logtype: [machinename]: LCM: [ Start Set ]
@@ -40,7 +53,7 @@ logtype: [machinename]: LCM: [ Start Resource ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources.length).to eq(1)
expect(resources[0].name).to eq("[name]")
end
@@ -54,7 +67,7 @@ logtype: [machinename]: LCM: [ End Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_truthy
end
@@ -68,11 +81,11 @@ logtype: [machinename]: LCM: [ End Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].change_log).to match_array(["[name]", "[message]", "[name]"])
end
- it "should return false for changes_state?" do
+ it "returns false for changes_state?" do
str = <<EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -80,11 +93,11 @@ logtype: [machinename]: LCM: [ Skip Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_falsey
end
- it "should return an empty array for change_log if changes_state? is false" do
+ it "returns an empty array for change_log if changes_state? is false" do
str = <<EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -92,13 +105,64 @@ logtype: [machinename]: LCM: [ Skip Set ] [name]
logtype: [machinename]: LCM: [ End Resource ] [name]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].change_log).to be_empty
end
end
- context "Incorrectly formatted output from LCM" do
- it "should allow missing a [End Resource] when its the last one and still find all the resource" do
+ context "correctly formatted output from lcm for TestDSCParser" do
+ it "returns a single resource when only 1 logged with the correct name" do
+ str = <<EOF
+InDesiredState : False
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name]
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources.length).to eq(1)
+ expect(resources[0].name).to eq("[name]")
+ end
+
+ it "identifies when a resource changes the state of the system" do
+ str = <<EOF
+InDesiredState : False
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name]
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].changes_state?).to be_truthy
+ end
+
+ it "returns false for changes_state?" do
+ str = <<EOF
+InDesiredState : True
+ResourcesInDesiredState : [name]
+ResourcesNotInDesiredState:
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].changes_state?).to be_falsey
+ end
+
+ it "returns an empty array for change_log if changes_state? is false" do
+ str = <<EOF
+InDesiredState : True
+ResourcesInDesiredState : [name]
+ResourcesNotInDesiredState:
+ReturnValue : 0
+PSComputerName : .
+EOF
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].change_log).to be_empty
+ end
+ end
+
+ context "Incorrectly formatted output from LCM for WhatIfParser" do
+ it "allows missing [End Resource] when its the last one and still find all the resource" do
str = <<-EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -114,12 +178,12 @@ logtype: [machinename]: LCM: [ End Set ]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_falsey
expect(resources[1].changes_state?).to be_truthy
end
- it "should allow missing a [End Resource] when its the first one and still find all the resource" do
+ it "allow missing [End Resource] when its the first one and still find all the resource" do
str = <<-EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -135,12 +199,12 @@ logtype: [machinename]: LCM: [ End Resource ]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_falsey
expect(resources[1].changes_state?).to be_truthy
end
- it "should allow missing set and end resource and assume an unconverged resource in this case" do
+ it "allows missing set and end resource and assume an unconverged resource in this case" do
str = <<-EOF
logtype: [machinename]: LCM: [ Start Set ]
logtype: [machinename]: LCM: [ Start Resource ] [name]
@@ -154,11 +218,31 @@ logtype: [machinename]: LCM: [ End Set ]
logtype: [machinename]: LCM: [ End Resource ]
logtype: [machinename]: LCM: [ End Set ]
EOF
- resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str)
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, false)
expect(resources[0].changes_state?).to be_truthy
expect(resources[0].name).to eql("[name]")
expect(resources[1].changes_state?).to be_truthy
expect(resources[1].name).to eql("[name2]")
end
end
+
+ context "Incorrectly formatted output from LCM for TestDSCParser" do
+ it "allows missing [End Resource] when its the last one and still find all the resource" do
+ str = <<EOF
+InDesiredState : True
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name]
+ReturnValue : 0
+PSComputerName : .
+InDesiredState : True
+ResourcesInDesiredState :
+ResourcesNotInDesiredState: [name2]
+ReturnValue : 0
+PSComputerName : .
+EOF
+
+ resources = Chef::Util::DSC::LocalConfigurationManager::Parser.parse(str, true)
+ expect(resources[0].changes_state?).to be_falsey
+ end
+ end
end
diff --git a/spec/unit/util/dsc/local_configuration_manager_spec.rb b/spec/unit/util/dsc/local_configuration_manager_spec.rb
index c87b446286..4c33fc8616 100644
--- a/spec/unit/util/dsc/local_configuration_manager_spec.rb
+++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb
@@ -57,6 +57,7 @@ EOH
context "when interacting with the LCM using a PowerShell cmdlet" do
before(:each) do
allow(lcm).to receive(:run_configuration_cmdlet).and_return(lcm_status)
+ allow(lcm).to receive(:ps_version_gte_5?).and_return(false)
end
context "that returns successfully" do
let(:lcm_standard_output) { normal_lcm_output }
@@ -103,7 +104,7 @@ EOH
let(:common_command_prefix) { "$ProgressPreference = 'SilentlyContinue';" }
let(:ps4_base_command) { "#{common_command_prefix} Start-DscConfiguration -path tmp -wait -erroraction 'stop' -force" }
let(:lcm_command_ps4) { ps4_base_command + " -whatif; if (! $?) { exit 1 }" }
- let(:lcm_command_ps5) { "#{common_command_prefix} Test-DscConfiguration -path tmp" }
+ let(:lcm_command_ps5) { "#{common_command_prefix} Test-DscConfiguration -path tmp | format-list" }
let(:lcm_standard_output) { normal_lcm_output }
let(:lcm_standard_error) { nil }
let(:lcm_cmdlet_success) { true }
diff --git a/spec/unit/util/selinux_spec.rb b/spec/unit/util/selinux_spec.rb
index 751092bc9a..5081281cf4 100644
--- a/spec/unit/util/selinux_spec.rb
+++ b/spec/unit/util/selinux_spec.rb
@@ -124,24 +124,21 @@ describe Chef::Util::Selinux do
end
it "should call restorecon non-recursive by default" do
- restorecon_command = "#{@restorecon_enabled_path} -R \"#{path}\""
- expect(@test_instance).to receive(:shell_out!).twice.with(restorecon_command)
+ expect(@test_instance).to receive(:shell_out_compact!).twice.with(@restorecon_enabled_path, [ "-R", path ])
@test_instance.restore_security_context(path)
expect(File).not_to receive(:executable?)
@test_instance.restore_security_context(path)
end
it "should call restorecon recursive when recursive is set" do
- restorecon_command = "#{@restorecon_enabled_path} -R -r \"#{path}\""
- expect(@test_instance).to receive(:shell_out!).twice.with(restorecon_command)
+ expect(@test_instance).to receive(:shell_out_compact!).twice.with(@restorecon_enabled_path, [ "-R", "-r", path ])
@test_instance.restore_security_context(path, true)
expect(File).not_to receive(:executable?)
@test_instance.restore_security_context(path, true)
end
it "should call restorecon non-recursive when recursive is not set" do
- restorecon_command = "#{@restorecon_enabled_path} -R \"#{path}\""
- expect(@test_instance).to receive(:shell_out!).twice.with(restorecon_command)
+ expect(@test_instance).to receive(:shell_out_compact!).twice.with(@restorecon_enabled_path, [ "-R", path ])
@test_instance.restore_security_context(path)
expect(File).not_to receive(:executable?)
@test_instance.restore_security_context(path)
diff --git a/spec/unit/util/windows/logon_session_spec.rb b/spec/unit/util/windows/logon_session_spec.rb
index b9b6c458b6..8a94802bf6 100644
--- a/spec/unit/util/windows/logon_session_spec.rb
+++ b/spec/unit/util/windows/logon_session_spec.rb
@@ -27,7 +27,8 @@ describe ::Chef::Util::Windows::LogonSession do
stub_const("Chef::ReservedNames::Win32::API::System", Class.new )
end
- let(:session) { ::Chef::Util::Windows::LogonSession.new(session_user, password, session_domain) }
+ let(:session) { ::Chef::Util::Windows::LogonSession.new(session_user, password, session_domain, authentication) }
+ let(:authentication) { :remote }
shared_examples_for "it received syntactically invalid credentials" do
it "does not raisees an exception when it is initialized" do
diff --git a/spec/unit/win32/security_spec.rb b/spec/unit/win32/security_spec.rb
index 1c755061ce..6e4441a482 100644
--- a/spec/unit/win32/security_spec.rb
+++ b/spec/unit/win32/security_spec.rb
@@ -63,4 +63,55 @@ describe "Chef::Win32::Security", :windows_only do
end
end
end
+
+ describe "self.has_admin_privileges?" do
+ it "returns true for windows server 2003" do
+ allow(Chef::Platform).to receive(:windows_server_2003?).and_return(true)
+ expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to be true
+ end
+
+ context "when the user doesn't have admin privileges" do
+ it "returns false" do
+ allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false)
+ allow(Chef::ReservedNames::Win32::Security).to receive(:open_current_process_token).and_raise("Access is denied.")
+ expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to be false
+ end
+ end
+
+ context "when open_current_process_token fails with some other error than `Access is Denied`" do
+ it "raises error" do
+ allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false)
+ allow(Chef::ReservedNames::Win32::Security).to receive(:open_current_process_token).and_raise("boom")
+ expect { Chef::ReservedNames::Win32::Security.has_admin_privileges? }.to raise_error(Chef::Exceptions::Win32APIError)
+ end
+ end
+
+ context "when the user has admin privileges" do
+ it "returns true" do
+ allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false)
+ allow(Chef::ReservedNames::Win32::Security).to receive(:open_current_process_token)
+ token = Chef::ReservedNames::Win32::Security.open_current_process_token
+ allow(token).to receive_message_chain(:handle, :handle)
+ allow(Chef::ReservedNames::Win32::Security).to receive(:get_token_information_elevation_type)
+ allow(Chef::ReservedNames::Win32::Security).to receive(:GetTokenInformation).and_return(true)
+ allow_any_instance_of(FFI::Buffer).to receive(:read_ulong).and_return(1)
+ expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to be true
+ end
+ end
+ end
+
+ describe "self.get_token_information_elevation_type" do
+ let(:token_rights) { Chef::ReservedNames::Win32::Security::TOKEN_READ }
+
+ let(:token) do
+ Chef::ReservedNames::Win32::Security.open_process_token(
+ Chef::ReservedNames::Win32::Process.get_current_process,
+ token_rights)
+ end
+
+ it "raises error if GetTokenInformation fails" do
+ allow(Chef::ReservedNames::Win32::Security).to receive(:GetTokenInformation).and_return(false)
+ expect { Chef::ReservedNames::Win32::Security.get_token_information_elevation_type(token) }.to raise_error(Chef::Exceptions::Win32APIError)
+ end
+ end
end
diff --git a/tasks/cbgb.rb b/tasks/cbgb.rb
index 70ca1036e8..09363b42d2 100644
--- a/tasks/cbgb.rb
+++ b/tasks/cbgb.rb
@@ -52,7 +52,7 @@ begin
def components(list, cmp)
out = ""
- cmp.each do |k, v|
+ cmp.each_value do |v|
out << "\n#### #{v['title'].gsub('#', '\\#')}\n"
out << cbgb(list, v["cbgb"])
end
diff --git a/tasks/dependencies.rb b/tasks/dependencies.rb
index 1c4ec14911..1dba2b4190 100644
--- a/tasks/dependencies.rb
+++ b/tasks/dependencies.rb
@@ -39,8 +39,6 @@ namespace :dependencies do
dependencies:update_gemfile_lock
dependencies:update_omnibus_gemfile_lock
dependencies:update_acceptance_gemfile_lock
- dependencies:update_kitchen_tests_gemfile_lock
- dependencies:update_kitchen_tests_berksfile_lock
dependencies:update_audit_tests_berksfile_lock
}
@@ -84,9 +82,6 @@ namespace :dependencies do
bundle_update_locked_multiplatform_task :update_gemfile_lock, "."
bundle_update_locked_multiplatform_task :update_omnibus_gemfile_lock, "omnibus"
bundle_update_task :update_acceptance_gemfile_lock, "acceptance"
- bundle_update_locked_multiplatform_task :update_kitchen_tests_gemfile_lock, "kitchen-tests"
-
- berks_update_task :update_kitchen_tests_berksfile_lock, "kitchen-tests"
berks_update_task :update_audit_tests_berksfile_lock, "kitchen-tests/cookbooks/audit_test"
end
diff --git a/tasks/maintainers.rb b/tasks/maintainers.rb
index f6385860c4..d2fc482a28 100644
--- a/tasks/maintainers.rb
+++ b/tasks/maintainers.rb
@@ -1,5 +1,5 @@
#
-# Copyright:: Copyright 2015-2016, Chef Software, Inc.
+# Copyright:: Copyright 2015-2018, Chef Software Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -131,7 +131,7 @@ begin
else
%w{maintainers lieutenant title}.each { |k| cmp.delete(k) }
end
- cmp.each { |_k, v| prepare_teams(v) }
+ cmp.each_value { |v| prepare_teams(v) }
end
def update_team(team, additions, deletions)
@@ -189,7 +189,7 @@ begin
end
out << format_maintainers(cmp.delete("maintainers")) + "\n" if cmp.has_key?("maintainers")
cmp.delete("paths")
- cmp.each { |k, v| out << format_components(v) }
+ cmp.each_value { |v| out << format_components(v) }
out
end
diff --git a/tasks/rspec.rb b/tasks/rspec.rb
index 616a68f09e..848c50eb40 100644
--- a/tasks/rspec.rb
+++ b/tasks/rspec.rb
@@ -25,7 +25,7 @@ CHEF_ROOT = File.join(File.dirname(__FILE__), "..")
begin
require "rspec/core/rake_task"
- desc "Run specs for Chef's Components"
+ desc "Run specs for Chef's Components (chef-config)"
task :component_specs do
Dir.chdir("chef-config") do
Bundler.with_clean_env do