knife 18.6.13 → 18.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (673) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +23 -23
  3. data/LICENSE +201 -201
  4. data/Rakefile +33 -33
  5. data/bin/knife +24 -24
  6. data/knife.gemspec +65 -65
  7. data/lib/chef/application/knife.rb +237 -237
  8. data/lib/chef/chef_fs/knife.rb +162 -162
  9. data/lib/chef/knife/acl_add.rb +57 -57
  10. data/lib/chef/knife/acl_base.rb +183 -183
  11. data/lib/chef/knife/acl_bulk_add.rb +78 -78
  12. data/lib/chef/knife/acl_bulk_remove.rb +83 -83
  13. data/lib/chef/knife/acl_remove.rb +62 -62
  14. data/lib/chef/knife/acl_show.rb +56 -56
  15. data/lib/chef/knife/bootstrap/chef_vault_handler.rb +160 -160
  16. data/lib/chef/knife/bootstrap/client_builder.rb +212 -212
  17. data/lib/chef/knife/bootstrap/templates/README.md +11 -11
  18. data/lib/chef/knife/bootstrap/templates/chef-full.erb +249 -249
  19. data/lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb +278 -278
  20. data/lib/chef/knife/bootstrap/train_connector.rb +334 -334
  21. data/lib/chef/knife/bootstrap.rb +1229 -1224
  22. data/lib/chef/knife/client_bulk_delete.rb +104 -104
  23. data/lib/chef/knife/client_create.rb +140 -140
  24. data/lib/chef/knife/client_delete.rb +62 -62
  25. data/lib/chef/knife/client_edit.rb +52 -52
  26. data/lib/chef/knife/client_key_create.rb +73 -73
  27. data/lib/chef/knife/client_key_delete.rb +80 -80
  28. data/lib/chef/knife/client_key_edit.rb +83 -83
  29. data/lib/chef/knife/client_key_list.rb +73 -73
  30. data/lib/chef/knife/client_key_show.rb +80 -80
  31. data/lib/chef/knife/client_list.rb +41 -41
  32. data/lib/chef/knife/client_reregister.rb +58 -58
  33. data/lib/chef/knife/client_show.rb +48 -48
  34. data/lib/chef/knife/config_get.rb +39 -39
  35. data/lib/chef/knife/config_get_profile.rb +37 -37
  36. data/lib/chef/knife/config_list.rb +139 -139
  37. data/lib/chef/knife/config_list_profiles.rb +37 -37
  38. data/lib/chef/knife/config_show.rb +127 -127
  39. data/lib/chef/knife/config_use.rb +61 -61
  40. data/lib/chef/knife/config_use_profile.rb +47 -47
  41. data/lib/chef/knife/configure.rb +150 -150
  42. data/lib/chef/knife/configure_client.rb +48 -48
  43. data/lib/chef/knife/cookbook_bulk_delete.rb +71 -71
  44. data/lib/chef/knife/cookbook_delete.rb +151 -151
  45. data/lib/chef/knife/cookbook_download.rb +142 -142
  46. data/lib/chef/knife/cookbook_list.rb +47 -47
  47. data/lib/chef/knife/cookbook_metadata.rb +106 -106
  48. data/lib/chef/knife/cookbook_metadata_from_file.rb +49 -49
  49. data/lib/chef/knife/cookbook_show.rb +98 -98
  50. data/lib/chef/knife/cookbook_upload.rb +313 -313
  51. data/lib/chef/knife/core/bootstrap_context.rb +274 -274
  52. data/lib/chef/knife/core/cookbook_scm_repo.rb +159 -159
  53. data/lib/chef/knife/core/cookbook_site_streaming_uploader.rb +249 -249
  54. data/lib/chef/knife/core/formatting_options.rb +49 -49
  55. data/lib/chef/knife/core/gem_glob_loader.rb +134 -134
  56. data/lib/chef/knife/core/generic_presenter.rb +238 -238
  57. data/lib/chef/knife/core/hashed_command_loader.rb +100 -100
  58. data/lib/chef/knife/core/node_editor.rb +130 -130
  59. data/lib/chef/knife/core/node_presenter.rb +133 -133
  60. data/lib/chef/knife/core/object_loader.rb +115 -115
  61. data/lib/chef/knife/core/status_presenter.rb +147 -147
  62. data/lib/chef/knife/core/subcommand_loader.rb +208 -208
  63. data/lib/chef/knife/core/text_formatter.rb +85 -85
  64. data/lib/chef/knife/core/ui.rb +339 -339
  65. data/lib/chef/knife/core/windows_bootstrap_context.rb +441 -443
  66. data/lib/chef/knife/data_bag_create.rb +81 -81
  67. data/lib/chef/knife/data_bag_delete.rb +49 -49
  68. data/lib/chef/knife/data_bag_edit.rb +74 -74
  69. data/lib/chef/knife/data_bag_from_file.rb +113 -113
  70. data/lib/chef/knife/data_bag_list.rb +42 -42
  71. data/lib/chef/knife/data_bag_secret_options.rb +122 -122
  72. data/lib/chef/knife/data_bag_show.rb +69 -69
  73. data/lib/chef/knife/delete.rb +125 -125
  74. data/lib/chef/knife/deps.rb +156 -156
  75. data/lib/chef/knife/diff.rb +83 -83
  76. data/lib/chef/knife/download.rb +85 -85
  77. data/lib/chef/knife/edit.rb +88 -88
  78. data/lib/chef/knife/environment_compare.rb +128 -128
  79. data/lib/chef/knife/environment_create.rb +52 -52
  80. data/lib/chef/knife/environment_delete.rb +44 -44
  81. data/lib/chef/knife/environment_edit.rb +44 -44
  82. data/lib/chef/knife/environment_from_file.rb +84 -84
  83. data/lib/chef/knife/environment_list.rb +41 -41
  84. data/lib/chef/knife/environment_show.rb +47 -47
  85. data/lib/chef/knife/exec.rb +99 -99
  86. data/lib/chef/knife/group_add.rb +55 -55
  87. data/lib/chef/knife/group_create.rb +49 -49
  88. data/lib/chef/knife/group_destroy.rb +53 -53
  89. data/lib/chef/knife/group_list.rb +43 -43
  90. data/lib/chef/knife/group_remove.rb +56 -56
  91. data/lib/chef/knife/group_show.rb +49 -49
  92. data/lib/chef/knife/key_create.rb +112 -112
  93. data/lib/chef/knife/key_create_base.rb +50 -50
  94. data/lib/chef/knife/key_delete.rb +55 -55
  95. data/lib/chef/knife/key_edit.rb +118 -118
  96. data/lib/chef/knife/key_edit_base.rb +55 -55
  97. data/lib/chef/knife/key_list.rb +90 -90
  98. data/lib/chef/knife/key_list_base.rb +45 -45
  99. data/lib/chef/knife/key_show.rb +53 -53
  100. data/lib/chef/knife/license.rb +52 -52
  101. data/lib/chef/knife/list.rb +177 -177
  102. data/lib/chef/knife/node_bulk_delete.rb +75 -75
  103. data/lib/chef/knife/node_create.rb +47 -47
  104. data/lib/chef/knife/node_delete.rb +46 -46
  105. data/lib/chef/knife/node_edit.rb +70 -70
  106. data/lib/chef/knife/node_environment_set.rb +53 -53
  107. data/lib/chef/knife/node_from_file.rb +51 -51
  108. data/lib/chef/knife/node_list.rb +44 -44
  109. data/lib/chef/knife/node_policy_set.rb +79 -79
  110. data/lib/chef/knife/node_run_list_add.rb +104 -104
  111. data/lib/chef/knife/node_run_list_remove.rb +67 -67
  112. data/lib/chef/knife/node_run_list_set.rb +66 -66
  113. data/lib/chef/knife/node_show.rb +63 -63
  114. data/lib/chef/knife/null.rb +12 -12
  115. data/lib/chef/knife/org_create.rb +70 -70
  116. data/lib/chef/knife/org_delete.rb +32 -32
  117. data/lib/chef/knife/org_edit.rb +48 -48
  118. data/lib/chef/knife/org_list.rb +44 -44
  119. data/lib/chef/knife/org_show.rb +31 -31
  120. data/lib/chef/knife/org_user_add.rb +62 -62
  121. data/lib/chef/knife/org_user_remove.rb +103 -103
  122. data/lib/chef/knife/raw.rb +123 -123
  123. data/lib/chef/knife/recipe_list.rb +32 -32
  124. data/lib/chef/knife/rehash.rb +50 -50
  125. data/lib/chef/knife/role_bulk_delete.rb +66 -66
  126. data/lib/chef/knife/role_create.rb +53 -53
  127. data/lib/chef/knife/role_delete.rb +46 -46
  128. data/lib/chef/knife/role_edit.rb +45 -45
  129. data/lib/chef/knife/role_env_run_list_add.rb +87 -87
  130. data/lib/chef/knife/role_env_run_list_clear.rb +55 -55
  131. data/lib/chef/knife/role_env_run_list_remove.rb +57 -57
  132. data/lib/chef/knife/role_env_run_list_replace.rb +60 -60
  133. data/lib/chef/knife/role_env_run_list_set.rb +70 -70
  134. data/lib/chef/knife/role_from_file.rb +51 -51
  135. data/lib/chef/knife/role_list.rb +42 -42
  136. data/lib/chef/knife/role_run_list_add.rb +87 -87
  137. data/lib/chef/knife/role_run_list_clear.rb +55 -55
  138. data/lib/chef/knife/role_run_list_remove.rb +56 -56
  139. data/lib/chef/knife/role_run_list_replace.rb +60 -60
  140. data/lib/chef/knife/role_run_list_set.rb +69 -69
  141. data/lib/chef/knife/role_show.rb +48 -48
  142. data/lib/chef/knife/search.rb +194 -194
  143. data/lib/chef/knife/serve.rb +65 -65
  144. data/lib/chef/knife/show.rb +72 -72
  145. data/lib/chef/knife/ssh.rb +657 -657
  146. data/lib/chef/knife/ssl_check.rb +284 -284
  147. data/lib/chef/knife/ssl_fetch.rb +162 -162
  148. data/lib/chef/knife/status.rb +95 -95
  149. data/lib/chef/knife/supermarket_download.rb +119 -119
  150. data/lib/chef/knife/supermarket_install.rb +192 -192
  151. data/lib/chef/knife/supermarket_list.rb +76 -76
  152. data/lib/chef/knife/supermarket_search.rb +53 -53
  153. data/lib/chef/knife/supermarket_share.rb +166 -166
  154. data/lib/chef/knife/supermarket_show.rb +66 -66
  155. data/lib/chef/knife/supermarket_unshare.rb +62 -62
  156. data/lib/chef/knife/tag_create.rb +52 -52
  157. data/lib/chef/knife/tag_delete.rb +60 -60
  158. data/lib/chef/knife/tag_list.rb +47 -47
  159. data/lib/chef/knife/upload.rb +87 -87
  160. data/lib/chef/knife/user_create.rb +180 -180
  161. data/lib/chef/knife/user_delete.rb +151 -151
  162. data/lib/chef/knife/user_dissociate.rb +42 -42
  163. data/lib/chef/knife/user_edit.rb +94 -94
  164. data/lib/chef/knife/user_invite_add.rb +43 -43
  165. data/lib/chef/knife/user_invite_list.rb +34 -34
  166. data/lib/chef/knife/user_invite_rescind.rb +63 -63
  167. data/lib/chef/knife/user_key_create.rb +73 -73
  168. data/lib/chef/knife/user_key_delete.rb +80 -80
  169. data/lib/chef/knife/user_key_edit.rb +83 -83
  170. data/lib/chef/knife/user_key_list.rb +73 -73
  171. data/lib/chef/knife/user_key_show.rb +80 -80
  172. data/lib/chef/knife/user_list.rb +43 -43
  173. data/lib/chef/knife/user_password.rb +70 -70
  174. data/lib/chef/knife/user_reregister.rb +59 -59
  175. data/lib/chef/knife/user_show.rb +52 -52
  176. data/lib/chef/knife/version.rb +24 -24
  177. data/lib/chef/knife/xargs.rb +282 -282
  178. data/lib/chef/knife/yaml_convert.rb +91 -91
  179. data/lib/chef/knife.rb +677 -677
  180. data/lib/chef/utils/licensing_config.rb +9 -9
  181. data/lib/chef/utils/licensing_handler.rb +72 -53
  182. data/spec/data/apt/chef-integration-test-1.0/debian/changelog +5 -5
  183. data/spec/data/apt/chef-integration-test-1.0/debian/compat +1 -1
  184. data/spec/data/apt/chef-integration-test-1.0/debian/control +13 -13
  185. data/spec/data/apt/chef-integration-test-1.0/debian/copyright +34 -34
  186. data/spec/data/apt/chef-integration-test-1.0/debian/files +1 -1
  187. data/spec/data/apt/chef-integration-test-1.0/debian/rules +13 -13
  188. data/spec/data/apt/chef-integration-test-1.0/debian/source/format +1 -1
  189. data/spec/data/apt/chef-integration-test-1.1/debian/changelog +11 -11
  190. data/spec/data/apt/chef-integration-test-1.1/debian/compat +1 -1
  191. data/spec/data/apt/chef-integration-test-1.1/debian/control +13 -13
  192. data/spec/data/apt/chef-integration-test-1.1/debian/copyright +34 -34
  193. data/spec/data/apt/chef-integration-test-1.1/debian/files +1 -1
  194. data/spec/data/apt/chef-integration-test-1.1/debian/rules +13 -13
  195. data/spec/data/apt/chef-integration-test-1.1/debian/source/format +1 -1
  196. data/spec/data/apt/chef-integration-test2-1.0/debian/changelog +5 -5
  197. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/conffiles +1 -1
  198. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/control +10 -10
  199. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/md5sums +1 -1
  200. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.debhelper.log +45 -45
  201. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.substvars +1 -1
  202. data/spec/data/apt/chef-integration-test2-1.0/debian/compat +1 -1
  203. data/spec/data/apt/chef-integration-test2-1.0/debian/conffiles +1 -1
  204. data/spec/data/apt/chef-integration-test2-1.0/debian/control +13 -13
  205. data/spec/data/apt/chef-integration-test2-1.0/debian/copyright +34 -34
  206. data/spec/data/apt/chef-integration-test2-1.0/debian/files +1 -1
  207. data/spec/data/apt/chef-integration-test2-1.0/debian/rules +13 -13
  208. data/spec/data/apt/chef-integration-test2-1.0/debian/source/format +1 -1
  209. data/spec/data/apt/chef-integration-test2_1.0-1.dsc +18 -18
  210. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.build +91 -91
  211. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes +31 -31
  212. data/spec/data/apt/chef-integration-test_1.0-1_amd64.changes +22 -22
  213. data/spec/data/apt/chef-integration-test_1.1-1_amd64.changes +22 -22
  214. data/spec/data/apt/var/www/apt/conf/distributions +7 -7
  215. data/spec/data/apt/var/www/apt/conf/incoming +4 -4
  216. data/spec/data/apt/var/www/apt/conf/pulls +3 -3
  217. data/spec/data/apt/var/www/apt/db/version +4 -4
  218. data/spec/data/apt/var/www/apt/dists/sid/Release +19 -19
  219. data/spec/data/apt/var/www/apt/dists/sid/main/binary-amd64/Packages +16 -16
  220. data/spec/data/apt/var/www/apt/dists/sid/main/binary-amd64/Release +5 -5
  221. data/spec/data/bootstrap/encrypted_data_bag_secret +1 -1
  222. data/spec/data/bootstrap/no_proxy.erb +2 -2
  223. data/spec/data/bootstrap/secret.erb +9 -9
  224. data/spec/data/bootstrap/test-hints.erb +12 -12
  225. data/spec/data/bootstrap/test.erb +1 -1
  226. data/spec/data/cb_version_cookbooks/tatft/README.rdoc +2 -2
  227. data/spec/data/cb_version_cookbooks/tatft/attributes/default.rb +1 -1
  228. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-600hhz-0 +1 -1
  229. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ahd2gq-0 +1 -1
  230. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-api8ux-0 +1 -1
  231. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-b0r1m1-0 +1 -1
  232. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-bfygsi-0 +1 -1
  233. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-el14l6-0 +1 -1
  234. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ivrl3y-0 +1 -1
  235. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-kkbs85-0 +1 -1
  236. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ory1ux-0 +1 -1
  237. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-pgsq76-0 +1 -1
  238. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ra8uim-0 +1 -1
  239. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-t7k1g-0 +1 -1
  240. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-t8g0sv-0 +1 -1
  241. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ufy6g3-0 +1 -1
  242. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-x2d6j9-0 +1 -1
  243. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-xi0l6h-0 +1 -1
  244. data/spec/data/client.d_00/00-foo.rb +2 -2
  245. data/spec/data/client.d_00/01-bar.rb +1 -1
  246. data/spec/data/client.d_00/02-strings.rb +2 -2
  247. data/spec/data/client.d_00/bar +1 -1
  248. data/spec/data/client.d_01/foo/bar.rb +1 -1
  249. data/spec/data/client.d_02/foo.rb/foo.txt +1 -1
  250. data/spec/data/config.rb +6 -6
  251. data/spec/data/cookbooks/angrybash/metadata.rb +2 -2
  252. data/spec/data/cookbooks/angrybash/recipes/default.rb +8 -8
  253. data/spec/data/cookbooks/apache2/files/default/apache2_module_conf_generate.pl +2 -2
  254. data/spec/data/cookbooks/apache2/metadata.json +33 -33
  255. data/spec/data/cookbooks/apache2/metadata.rb +2 -2
  256. data/spec/data/cookbooks/apache2/recipes/default.rb +2 -2
  257. data/spec/data/cookbooks/borken/metadata.rb +2 -2
  258. data/spec/data/cookbooks/borken/recipes/default.rb +1 -1
  259. data/spec/data/cookbooks/borken/templates/default/borken.erb +1 -1
  260. data/spec/data/cookbooks/chefignore +8 -8
  261. data/spec/data/cookbooks/ignorken/files/default/not_me.rb +2 -2
  262. data/spec/data/cookbooks/ignorken/metadata.rb +2 -2
  263. data/spec/data/cookbooks/ignorken/recipes/ignoreme.rb +1 -1
  264. data/spec/data/cookbooks/ignorken/templates/ubuntu-12.10/not_me.rb +2 -2
  265. data/spec/data/cookbooks/irssi/files/default/irssi.response +2 -2
  266. data/spec/data/cookbooks/java/files/default/java.response +1 -1
  267. data/spec/data/cookbooks/java/metadata.json +33 -33
  268. data/spec/data/cookbooks/java/metadata.rb +2 -2
  269. data/spec/data/cookbooks/name-mismatch-versionnumber/README.md +4 -4
  270. data/spec/data/cookbooks/name-mismatch-versionnumber/metadata.rb +8 -8
  271. data/spec/data/cookbooks/name-mismatch-versionnumber/recipes/default.rb +8 -8
  272. data/spec/data/cookbooks/openldap/attributes/default.rb +16 -16
  273. data/spec/data/cookbooks/openldap/attributes/smokey.rb +1 -1
  274. data/spec/data/cookbooks/openldap/definitions/client.rb +5 -5
  275. data/spec/data/cookbooks/openldap/definitions/server.rb +5 -5
  276. data/spec/data/cookbooks/openldap/files/default/.dotfile +1 -1
  277. data/spec/data/cookbooks/openldap/files/default/remotedir/.a_dotdir/.a_dotfile_in_a_dotdir +1 -1
  278. data/spec/data/cookbooks/openldap/files/default/remotedir/not_a_template.erb +2 -2
  279. data/spec/data/cookbooks/openldap/files/default/remotedir/remote_dir_file1.txt +2 -2
  280. data/spec/data/cookbooks/openldap/files/default/remotedir/remote_dir_file2.txt +2 -2
  281. data/spec/data/cookbooks/openldap/files/default/remotedir/remotesubdir/.a_dotfile +1 -1
  282. data/spec/data/cookbooks/openldap/files/default/remotedir/remotesubdir/remote_subdir_file1.txt +2 -2
  283. data/spec/data/cookbooks/openldap/files/default/remotedir/remotesubdir/remote_subdir_file2.txt +2 -2
  284. data/spec/data/cookbooks/openldap/files/default/remotedir/subdir_with_no_file_just_a_subsubdir/the_subsubdir/some_file.txt +3 -3
  285. data/spec/data/cookbooks/openldap/libraries/openldap/version.rb +3 -3
  286. data/spec/data/cookbooks/openldap/libraries/openldap.rb +4 -4
  287. data/spec/data/cookbooks/openldap/metadata.rb +8 -8
  288. data/spec/data/cookbooks/openldap/recipes/default.rb +4 -4
  289. data/spec/data/cookbooks/openldap/recipes/gigantor.rb +3 -3
  290. data/spec/data/cookbooks/openldap/recipes/one.rb +15 -15
  291. data/spec/data/cookbooks/openldap/recipes/return.rb +2 -2
  292. data/spec/data/cookbooks/openldap/templates/default/helper_test.erb +1 -1
  293. data/spec/data/cookbooks/openldap/templates/default/helpers.erb +14 -14
  294. data/spec/data/cookbooks/openldap/templates/default/helpers_via_partial_test.erb +1 -1
  295. data/spec/data/cookbooks/openldap/templates/default/nested_openldap_partials.erb +1 -1
  296. data/spec/data/cookbooks/openldap/templates/default/nested_partial.erb +1 -1
  297. data/spec/data/cookbooks/openldap/templates/default/no_windows_line_endings.erb +4 -4
  298. data/spec/data/cookbooks/openldap/templates/default/openldap_nested_variable_stuff.erb +1 -1
  299. data/spec/data/cookbooks/openldap/templates/default/openldap_variable_stuff.conf.erb +1 -1
  300. data/spec/data/cookbooks/openldap/templates/default/test.erb +1 -1
  301. data/spec/data/cookbooks/preseed/files/default/preseed-file.seed +1 -1
  302. data/spec/data/cookbooks/preseed/files/default/preseed-template.seed +4 -4
  303. data/spec/data/cookbooks/preseed/metadata.rb +2 -2
  304. data/spec/data/cookbooks/preseed/templates/default/preseed-template-variables.seed +1 -1
  305. data/spec/data/cookbooks/preseed/templates/default/preseed-template.seed +1 -1
  306. data/spec/data/cookbooks/starter/chefignore +8 -8
  307. data/spec/data/cookbooks/starter/metadata.rb +2 -2
  308. data/spec/data/cookbooks/starter/recipes/default.rb +4 -4
  309. data/spec/data/cookbooks/supports-platform-constraints/metadata.rb +5 -5
  310. data/spec/data/cookbooks/wget/files/default/wget.response +2 -2
  311. data/spec/data/definitions/test.rb +4 -4
  312. data/spec/data/environment-config.rb +4 -4
  313. data/spec/data/file-providers-method-snapshot-chef-11-4.json +127 -127
  314. data/spec/data/fileedit/hosts +4 -4
  315. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/README.md +4 -4
  316. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/metadata.rb +13 -13
  317. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/recipes/default.rb +8 -8
  318. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/README.md +4 -4
  319. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/metadata.rb +9 -9
  320. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/recipes/default.rb +8 -8
  321. data/spec/data/kitchen/chefignore +6 -6
  322. data/spec/data/kitchen/openldap/attributes/default.rb +3 -3
  323. data/spec/data/kitchen/openldap/attributes/robinson.rb +2 -2
  324. data/spec/data/kitchen/openldap/definitions/client.rb +3 -3
  325. data/spec/data/kitchen/openldap/definitions/drewbarrymore.rb +2 -2
  326. data/spec/data/kitchen/openldap/recipes/gigantor.rb +2 -2
  327. data/spec/data/kitchen/openldap/recipes/ignoreme.rb +2 -2
  328. data/spec/data/kitchen/openldap/recipes/woot.rb +3 -3
  329. data/spec/data/knife_subcommand/test_explicit_category.rb +6 -6
  330. data/spec/data/knife_subcommand/test_name_mapping.rb +4 -4
  331. data/spec/data/knife_subcommand/test_yourself.rb +21 -21
  332. data/spec/data/lwrp/providers/buck_passer.rb +28 -28
  333. data/spec/data/lwrp/providers/buck_passer_2.rb +26 -26
  334. data/spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb +28 -28
  335. data/spec/data/lwrp/providers/inline_compiler.rb +24 -24
  336. data/spec/data/lwrp/providers/monkey_name_printer.rb +5 -5
  337. data/spec/data/lwrp/providers/paint_drying_watcher.rb +7 -7
  338. data/spec/data/lwrp/providers/thumb_twiddler.rb +7 -7
  339. data/spec/data/lwrp/resources/bar.rb +4 -4
  340. data/spec/data/lwrp/resources/buck_passer.rb +6 -6
  341. data/spec/data/lwrp/resources/buck_passer_2.rb +4 -4
  342. data/spec/data/lwrp/resources/embedded_resource_accesses_providers_scope.rb +4 -4
  343. data/spec/data/lwrp/resources/foo.rb +6 -6
  344. data/spec/data/lwrp/resources/inline_compiler.rb +4 -4
  345. data/spec/data/lwrp/resources/monkey_name_printer.rb +6 -6
  346. data/spec/data/lwrp/resources/paint_drying_watcher.rb +4 -4
  347. data/spec/data/lwrp/resources/thumb_twiddler.rb +4 -4
  348. data/spec/data/lwrp/resources_with_default_attributes/nodeattr.rb +3 -3
  349. data/spec/data/lwrp_const_scoping/resources/conflict.rb +1 -1
  350. data/spec/data/lwrp_override/providers/buck_passer.rb +5 -5
  351. data/spec/data/lwrp_override/resources/foo.rb +11 -11
  352. data/spec/data/mac_users/10.9.plist.xml +560 -560
  353. data/spec/data/mac_users/10.9.shadow.xml +21 -21
  354. data/spec/data/metadata/quick_start/metadata.rb +14 -14
  355. data/spec/data/mixin/invalid_data.rb +3 -3
  356. data/spec/data/mixin/real_data.rb +2 -2
  357. data/spec/data/nested.json +2 -2
  358. data/spec/data/nodes/default.rb +15 -15
  359. data/spec/data/nodes/test.example.com.rb +17 -17
  360. data/spec/data/nodes/test.rb +15 -15
  361. data/spec/data/null_config.rb +1 -1
  362. data/spec/data/object_loader/environments/test.json +7 -7
  363. data/spec/data/object_loader/environments/test.rb +2 -2
  364. data/spec/data/object_loader/environments/test_json_class.json +8 -8
  365. data/spec/data/object_loader/nodes/test.json +7 -7
  366. data/spec/data/object_loader/nodes/test.rb +2 -2
  367. data/spec/data/object_loader/nodes/test_json_class.json +8 -8
  368. data/spec/data/object_loader/roles/test.json +7 -7
  369. data/spec/data/object_loader/roles/test.rb +2 -2
  370. data/spec/data/object_loader/roles/test_json_class.json +8 -8
  371. data/spec/data/partial_one.erb +1 -1
  372. data/spec/data/prefer_metadata_json/metadata.json +51 -51
  373. data/spec/data/prefer_metadata_json/metadata.rb +6 -6
  374. data/spec/data/recipes/test.rb +7 -7
  375. data/spec/data/root_alias_cookbooks/dup_attr/attributes/default.rb +1 -1
  376. data/spec/data/root_alias_cookbooks/dup_attr/attributes.rb +1 -1
  377. data/spec/data/root_alias_cookbooks/dup_attr/metadata.rb +2 -2
  378. data/spec/data/root_alias_cookbooks/dup_attr/recipe.rb +3 -3
  379. data/spec/data/root_alias_cookbooks/dup_recipe/attributes.rb +1 -1
  380. data/spec/data/root_alias_cookbooks/dup_recipe/metadata.rb +2 -2
  381. data/spec/data/root_alias_cookbooks/dup_recipe/recipe.rb +3 -3
  382. data/spec/data/root_alias_cookbooks/dup_recipe/recipes/default.rb +3 -3
  383. data/spec/data/root_alias_cookbooks/simple/attributes.rb +1 -1
  384. data/spec/data/root_alias_cookbooks/simple/metadata.rb +2 -2
  385. data/spec/data/root_alias_cookbooks/simple/recipe.rb +3 -3
  386. data/spec/data/rubygems.org/sexp_processor-info +49 -49
  387. data/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb +2 -2
  388. data/spec/data/run_context/cookbooks/circular-dep1/definitions/circular_dep1_res.rb +1 -1
  389. data/spec/data/run_context/cookbooks/circular-dep1/libraries/lib.rb +2 -2
  390. data/spec/data/run_context/cookbooks/circular-dep1/metadata.rb +2 -2
  391. data/spec/data/run_context/cookbooks/circular-dep1/providers/provider.rb +1 -1
  392. data/spec/data/run_context/cookbooks/circular-dep1/resources/resource.rb +2 -2
  393. data/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb +2 -2
  394. data/spec/data/run_context/cookbooks/circular-dep2/definitions/circular_dep2_res.rb +1 -1
  395. data/spec/data/run_context/cookbooks/circular-dep2/libraries/lib.rb +2 -2
  396. data/spec/data/run_context/cookbooks/circular-dep2/metadata.rb +2 -2
  397. data/spec/data/run_context/cookbooks/circular-dep2/providers/provider.rb +1 -1
  398. data/spec/data/run_context/cookbooks/circular-dep2/resources/resource.rb +2 -2
  399. data/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb +2 -2
  400. data/spec/data/run_context/cookbooks/dependency1/attributes/default.rb +2 -2
  401. data/spec/data/run_context/cookbooks/dependency1/attributes/unparsed_file +1 -1
  402. data/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb +2 -2
  403. data/spec/data/run_context/cookbooks/dependency1/definitions/dependency1_res.rb +1 -1
  404. data/spec/data/run_context/cookbooks/dependency1/definitions/unparsed_file +1 -1
  405. data/spec/data/run_context/cookbooks/dependency1/libraries/lib.rb +2 -2
  406. data/spec/data/run_context/cookbooks/dependency1/libraries/unparsed_file +1 -1
  407. data/spec/data/run_context/cookbooks/dependency1/providers/provider.rb +1 -1
  408. data/spec/data/run_context/cookbooks/dependency1/providers/unparsed_file +1 -1
  409. data/spec/data/run_context/cookbooks/dependency1/recipes/unparsed_file +1 -1
  410. data/spec/data/run_context/cookbooks/dependency1/resources/resource.rb +2 -2
  411. data/spec/data/run_context/cookbooks/dependency1/resources/unparsed_file +1 -1
  412. data/spec/data/run_context/cookbooks/dependency2/attributes/default.rb +2 -2
  413. data/spec/data/run_context/cookbooks/dependency2/definitions/dependency2_res.rb +1 -1
  414. data/spec/data/run_context/cookbooks/dependency2/libraries/lib.rb +2 -2
  415. data/spec/data/run_context/cookbooks/dependency2/providers/provider.rb +1 -1
  416. data/spec/data/run_context/cookbooks/dependency2/resources/resource.rb +2 -2
  417. data/spec/data/run_context/cookbooks/include/recipes/default.rb +24 -24
  418. data/spec/data/run_context/cookbooks/include/recipes/includee.rb +3 -3
  419. data/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb +2 -2
  420. data/spec/data/run_context/cookbooks/no-default-attr/definitions/no_default-attr_res.rb +1 -1
  421. data/spec/data/run_context/cookbooks/no-default-attr/providers/provider.rb +1 -1
  422. data/spec/data/run_context/cookbooks/no-default-attr/resources/resource.rb +2 -2
  423. data/spec/data/run_context/cookbooks/test/attributes/george.rb +1 -1
  424. data/spec/data/run_context/cookbooks/test/definitions/new_animals.rb +9 -9
  425. data/spec/data/run_context/cookbooks/test/definitions/new_cat.rb +5 -5
  426. data/spec/data/run_context/cookbooks/test/definitions/test_res.rb +1 -1
  427. data/spec/data/run_context/cookbooks/test/providers/provider.rb +1 -1
  428. data/spec/data/run_context/cookbooks/test/recipes/default.rb +5 -5
  429. data/spec/data/run_context/cookbooks/test/recipes/one.rb +7 -7
  430. data/spec/data/run_context/cookbooks/test/recipes/two.rb +7 -7
  431. data/spec/data/run_context/cookbooks/test/resources/resource.rb +3 -3
  432. data/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb +2 -2
  433. data/spec/data/run_context/cookbooks/test-with-circular-deps/definitions/test_with-circular-deps_res.rb +1 -1
  434. data/spec/data/run_context/cookbooks/test-with-circular-deps/libraries/lib.rb +2 -2
  435. data/spec/data/run_context/cookbooks/test-with-circular-deps/metadata.rb +2 -2
  436. data/spec/data/run_context/cookbooks/test-with-circular-deps/providers/provider.rb +1 -1
  437. data/spec/data/run_context/cookbooks/test-with-circular-deps/resources/resource.rb +3 -3
  438. data/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb +2 -2
  439. data/spec/data/run_context/cookbooks/test-with-deps/definitions/test_with-deps_res.rb +1 -1
  440. data/spec/data/run_context/cookbooks/test-with-deps/libraries/lib.rb +1 -1
  441. data/spec/data/run_context/cookbooks/test-with-deps/metadata.rb +3 -3
  442. data/spec/data/run_context/cookbooks/test-with-deps/providers/provider.rb +1 -1
  443. data/spec/data/run_context/cookbooks/test-with-deps/resources/resource.rb +2 -2
  444. data/spec/data/run_context/nodes/run_context.rb +5 -5
  445. data/spec/data/sample_msu1.xml +10 -10
  446. data/spec/data/sample_msu2.xml +14 -14
  447. data/spec/data/sample_msu3.xml +16 -16
  448. data/spec/data/search_queries_to_transform.txt +98 -98
  449. data/spec/data/shef-config.rb +11 -11
  450. data/spec/data/snap_package/async_result_success.json +6 -6
  451. data/spec/data/snap_package/change_id_result.json +175 -175
  452. data/spec/data/snap_package/find_result_failure.json +10 -10
  453. data/spec/data/snap_package/find_result_success.json +70 -70
  454. data/spec/data/snap_package/get_by_name_result_failure.json +10 -10
  455. data/spec/data/snap_package/get_by_name_result_success.json +38 -38
  456. data/spec/data/snap_package/get_conf_success.json +10 -10
  457. data/spec/data/snap_package/result_failure.json +9 -9
  458. data/spec/data/ssl/5e707473.0 +18 -18
  459. data/spec/data/ssl/chef-rspec.cert +27 -27
  460. data/spec/data/ssl/chef-rspec.key +27 -27
  461. data/spec/data/ssl/key.pem +15 -15
  462. data/spec/data/ssl/private_key.pem +27 -27
  463. data/spec/data/ssl/private_key_with_whitespace.pem +32 -32
  464. data/spec/data/standalone_cookbook/chefignore +9 -9
  465. data/spec/data/standalone_cookbook/recipes/default.rb +2 -2
  466. data/spec/data/templates/failed.erb +5 -5
  467. data/spec/data/trusted_certs/example.crt +22 -22
  468. data/spec/data/trusted_certs/example_no_cn.crt +36 -36
  469. data/spec/data/trusted_certs/intermediate.pem +27 -27
  470. data/spec/data/trusted_certs/opscode.pem +57 -57
  471. data/spec/data/trusted_certs/root.pem +22 -22
  472. data/spec/data/windows_certificates/base64_test.cer +20 -20
  473. data/spec/data/windows_certificates/othertest.cer +20 -20
  474. data/spec/data/windows_certificates/test.cer +20 -20
  475. data/spec/data/windows_certificates/test.pem +20 -20
  476. data/spec/functional/configure_spec.rb +33 -33
  477. data/spec/functional/cookbook_delete_spec.rb +157 -156
  478. data/spec/functional/exec_spec.rb +55 -55
  479. data/spec/functional/rehash_spec.rb +39 -39
  480. data/spec/functional/smoke_test.rb +42 -42
  481. data/spec/functional/ssh_spec.rb +352 -352
  482. data/spec/functional/version_spec.rb +26 -26
  483. data/spec/integration/chef_fs_data_store_spec.rb +557 -557
  484. data/spec/integration/chef_repo_path_spec.rb +962 -962
  485. data/spec/integration/chef_repository_file_system_spec.rb +200 -200
  486. data/spec/integration/chefignore_spec.rb +301 -301
  487. data/spec/integration/client_bulk_delete_spec.rb +131 -131
  488. data/spec/integration/client_create_spec.rb +70 -70
  489. data/spec/integration/client_delete_spec.rb +64 -64
  490. data/spec/integration/client_key_create_spec.rb +66 -66
  491. data/spec/integration/client_key_delete_spec.rb +43 -43
  492. data/spec/integration/client_key_list_spec.rb +61 -61
  493. data/spec/integration/client_key_show_spec.rb +45 -45
  494. data/spec/integration/client_list_spec.rb +49 -49
  495. data/spec/integration/client_show_spec.rb +37 -37
  496. data/spec/integration/commands_spec.rb +55 -55
  497. data/spec/integration/common_options_spec.rb +174 -174
  498. data/spec/integration/config_list_spec.rb +220 -220
  499. data/spec/integration/config_show_spec.rb +192 -192
  500. data/spec/integration/config_use_spec.rb +198 -198
  501. data/spec/integration/cookbook_api_ipv6_spec.rb +113 -113
  502. data/spec/integration/cookbook_bulk_delete_spec.rb +65 -65
  503. data/spec/integration/cookbook_download_spec.rb +72 -72
  504. data/spec/integration/cookbook_list_spec.rb +55 -55
  505. data/spec/integration/cookbook_show_spec.rb +149 -149
  506. data/spec/integration/cookbook_upload_spec.rb +128 -128
  507. data/spec/integration/data_bag_create_spec.rb +125 -125
  508. data/spec/integration/data_bag_delete_spec.rb +59 -59
  509. data/spec/integration/data_bag_edit_spec.rb +105 -105
  510. data/spec/integration/data_bag_from_file_spec.rb +116 -116
  511. data/spec/integration/data_bag_list_spec.rb +44 -44
  512. data/spec/integration/data_bag_show_spec.rb +95 -95
  513. data/spec/integration/delete_spec.rb +1018 -1018
  514. data/spec/integration/deps_spec.rb +703 -703
  515. data/spec/integration/diff_spec.rb +605 -605
  516. data/spec/integration/download_spec.rb +1336 -1336
  517. data/spec/integration/environment_compare_spec.rb +75 -75
  518. data/spec/integration/environment_create_spec.rb +41 -41
  519. data/spec/integration/environment_delete_spec.rb +37 -37
  520. data/spec/integration/environment_from_file_spec.rb +116 -116
  521. data/spec/integration/environment_list_spec.rb +42 -42
  522. data/spec/integration/environment_show_spec.rb +77 -77
  523. data/spec/integration/list_spec.rb +1060 -1060
  524. data/spec/integration/node_bulk_delete_spec.rb +52 -52
  525. data/spec/integration/node_create_spec.rb +47 -47
  526. data/spec/integration/node_delete_spec.rb +48 -48
  527. data/spec/integration/node_environment_set_spec.rb +46 -46
  528. data/spec/integration/node_from_file_spec.rb +59 -59
  529. data/spec/integration/node_list_spec.rb +45 -45
  530. data/spec/integration/node_run_list_add_spec.rb +54 -54
  531. data/spec/integration/node_run_list_remove_spec.rb +36 -36
  532. data/spec/integration/node_run_list_set_spec.rb +41 -41
  533. data/spec/integration/node_show_spec.rb +36 -36
  534. data/spec/integration/raw_spec.rb +297 -297
  535. data/spec/integration/redirection_spec.rb +64 -64
  536. data/spec/integration/role_bulk_delete_spec.rb +52 -52
  537. data/spec/integration/role_create_spec.rb +41 -41
  538. data/spec/integration/role_delete_spec.rb +48 -48
  539. data/spec/integration/role_from_file_spec.rb +96 -96
  540. data/spec/integration/role_list_spec.rb +45 -45
  541. data/spec/integration/role_show_spec.rb +51 -51
  542. data/spec/integration/search_node_spec.rb +40 -40
  543. data/spec/integration/serve_spec.rb +92 -92
  544. data/spec/integration/show_spec.rb +197 -197
  545. data/spec/integration/upload_spec.rb +1616 -1616
  546. data/spec/knife_spec_helper.rb +241 -241
  547. data/spec/support/chef_helpers.rb +79 -79
  548. data/spec/support/key_helpers.rb +102 -102
  549. data/spec/support/platform_helpers.rb +255 -255
  550. data/spec/support/platforms/prof/gc.rb +51 -51
  551. data/spec/support/platforms/prof/win32.rb +45 -45
  552. data/spec/support/platforms/win32/spec_service.rb +57 -57
  553. data/spec/support/recipe_dsl_helper.rb +83 -83
  554. data/spec/support/shared/context/config.rb +18 -18
  555. data/spec/support/shared/functional/knife.rb +37 -37
  556. data/spec/support/shared/integration/integration_helper.rb +122 -122
  557. data/spec/support/shared/integration/knife_support.rb +192 -192
  558. data/spec/support/shared/matchers/exit_with_code.rb +32 -32
  559. data/spec/support/shared/matchers/match_environment_variable.rb +17 -17
  560. data/spec/support/shared/unit/knife_shared.rb +39 -39
  561. data/spec/support/shared/unit/mock_shellout.rb +49 -49
  562. data/spec/tiny_server.rb +193 -190
  563. data/spec/unit/application/knife_spec.rb +241 -241
  564. data/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb +152 -152
  565. data/spec/unit/knife/bootstrap/client_builder_spec.rb +207 -207
  566. data/spec/unit/knife/bootstrap/train_connector_spec.rb +244 -244
  567. data/spec/unit/knife/bootstrap_spec.rb +2311 -2288
  568. data/spec/unit/knife/client_bulk_delete_spec.rb +166 -166
  569. data/spec/unit/knife/client_create_spec.rb +232 -232
  570. data/spec/unit/knife/client_delete_spec.rb +99 -99
  571. data/spec/unit/knife/client_edit_spec.rb +53 -53
  572. data/spec/unit/knife/client_list_spec.rb +34 -34
  573. data/spec/unit/knife/client_reregister_spec.rb +62 -62
  574. data/spec/unit/knife/client_show_spec.rb +52 -52
  575. data/spec/unit/knife/configure_client_spec.rb +81 -81
  576. data/spec/unit/knife/configure_spec.rb +190 -190
  577. data/spec/unit/knife/cookbook_bulk_delete_spec.rb +87 -87
  578. data/spec/unit/knife/cookbook_delete_spec.rb +239 -239
  579. data/spec/unit/knife/cookbook_download_spec.rb +255 -255
  580. data/spec/unit/knife/cookbook_list_spec.rb +88 -88
  581. data/spec/unit/knife/cookbook_metadata_from_file_spec.rb +72 -72
  582. data/spec/unit/knife/cookbook_metadata_spec.rb +182 -182
  583. data/spec/unit/knife/cookbook_show_spec.rb +253 -253
  584. data/spec/unit/knife/cookbook_upload_spec.rb +426 -426
  585. data/spec/unit/knife/core/bootstrap_context_spec.rb +287 -287
  586. data/spec/unit/knife/core/cookbook_scm_repo_spec.rb +187 -187
  587. data/spec/unit/knife/core/cookbook_site_streaming_uploader_spec.rb +198 -198
  588. data/spec/unit/knife/core/gem_glob_loader_spec.rb +242 -242
  589. data/spec/unit/knife/core/hashed_command_loader_spec.rb +112 -112
  590. data/spec/unit/knife/core/node_editor_spec.rb +211 -211
  591. data/spec/unit/knife/core/object_loader_spec.rb +81 -81
  592. data/spec/unit/knife/core/status_presenter_spec.rb +54 -54
  593. data/spec/unit/knife/core/subcommand_loader_spec.rb +64 -64
  594. data/spec/unit/knife/core/ui_spec.rb +656 -656
  595. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +282 -238
  596. data/spec/unit/knife/data_bag_create_spec.rb +175 -175
  597. data/spec/unit/knife/data_bag_edit_spec.rb +126 -126
  598. data/spec/unit/knife/data_bag_from_file_spec.rb +174 -174
  599. data/spec/unit/knife/data_bag_secret_options_spec.rb +173 -173
  600. data/spec/unit/knife/data_bag_show_spec.rb +139 -139
  601. data/spec/unit/knife/environment_compare_spec.rb +112 -112
  602. data/spec/unit/knife/environment_create_spec.rb +91 -91
  603. data/spec/unit/knife/environment_delete_spec.rb +71 -71
  604. data/spec/unit/knife/environment_edit_spec.rb +79 -79
  605. data/spec/unit/knife/environment_from_file_spec.rb +90 -90
  606. data/spec/unit/knife/environment_list_spec.rb +54 -54
  607. data/spec/unit/knife/environment_show_spec.rb +52 -52
  608. data/spec/unit/knife/key_create_spec.rb +223 -223
  609. data/spec/unit/knife/key_delete_spec.rb +133 -133
  610. data/spec/unit/knife/key_edit_spec.rb +264 -264
  611. data/spec/unit/knife/key_helper.rb +74 -74
  612. data/spec/unit/knife/key_list_spec.rb +216 -216
  613. data/spec/unit/knife/key_show_spec.rb +126 -126
  614. data/spec/unit/knife/license_spec.rb +89 -89
  615. data/spec/unit/knife/node_bulk_delete_spec.rb +94 -94
  616. data/spec/unit/knife/node_delete_spec.rb +77 -77
  617. data/spec/unit/knife/node_edit_spec.rb +116 -116
  618. data/spec/unit/knife/node_environment_set_spec.rb +61 -61
  619. data/spec/unit/knife/node_from_file_spec.rb +59 -59
  620. data/spec/unit/knife/node_list_spec.rb +62 -62
  621. data/spec/unit/knife/node_policy_set_spec.rb +122 -122
  622. data/spec/unit/knife/node_run_list_add_spec.rb +145 -145
  623. data/spec/unit/knife/node_run_list_remove_spec.rb +106 -106
  624. data/spec/unit/knife/node_run_list_set_spec.rb +115 -115
  625. data/spec/unit/knife/node_show_spec.rb +65 -65
  626. data/spec/unit/knife/org_create_spec.rb +76 -76
  627. data/spec/unit/knife/org_delete_spec.rb +41 -41
  628. data/spec/unit/knife/org_edit_spec.rb +49 -49
  629. data/spec/unit/knife/org_list_spec.rb +58 -58
  630. data/spec/unit/knife/org_show_spec.rb +45 -45
  631. data/spec/unit/knife/org_user_add_spec.rb +39 -39
  632. data/spec/unit/knife/raw_spec.rb +43 -43
  633. data/spec/unit/knife/role_bulk_delete_spec.rb +80 -80
  634. data/spec/unit/knife/role_create_spec.rb +80 -80
  635. data/spec/unit/knife/role_delete_spec.rb +67 -67
  636. data/spec/unit/knife/role_edit_spec.rb +77 -77
  637. data/spec/unit/knife/role_env_run_list_add_spec.rb +217 -217
  638. data/spec/unit/knife/role_env_run_list_clear_spec.rb +94 -94
  639. data/spec/unit/knife/role_env_run_list_remove_spec.rb +102 -102
  640. data/spec/unit/knife/role_env_run_list_replace_spec.rb +105 -105
  641. data/spec/unit/knife/role_env_run_list_set_spec.rb +99 -99
  642. data/spec/unit/knife/role_from_file_spec.rb +69 -69
  643. data/spec/unit/knife/role_list_spec.rb +54 -54
  644. data/spec/unit/knife/role_run_list_add_spec.rb +179 -179
  645. data/spec/unit/knife/role_run_list_clear_spec.rb +84 -84
  646. data/spec/unit/knife/role_run_list_remove_spec.rb +92 -92
  647. data/spec/unit/knife/role_run_list_replace_spec.rb +98 -98
  648. data/spec/unit/knife/role_run_list_set_spec.rb +89 -89
  649. data/spec/unit/knife/role_show_spec.rb +59 -59
  650. data/spec/unit/knife/search_spec.rb +147 -147
  651. data/spec/unit/knife/ssh_spec.rb +403 -403
  652. data/spec/unit/knife/ssl_check_spec.rb +256 -256
  653. data/spec/unit/knife/ssl_fetch_spec.rb +222 -222
  654. data/spec/unit/knife/status_spec.rb +112 -112
  655. data/spec/unit/knife/supermarket_download_spec.rb +152 -152
  656. data/spec/unit/knife/supermarket_install_spec.rb +203 -203
  657. data/spec/unit/knife/supermarket_list_spec.rb +70 -70
  658. data/spec/unit/knife/supermarket_search_spec.rb +85 -85
  659. data/spec/unit/knife/supermarket_share_spec.rb +208 -208
  660. data/spec/unit/knife/supermarket_unshare_spec.rb +78 -78
  661. data/spec/unit/knife/tag_create_spec.rb +23 -23
  662. data/spec/unit/knife/tag_delete_spec.rb +25 -25
  663. data/spec/unit/knife/tag_list_spec.rb +23 -23
  664. data/spec/unit/knife/user_create_spec.rb +282 -282
  665. data/spec/unit/knife/user_delete_spec.rb +171 -171
  666. data/spec/unit/knife/user_edit_spec.rb +54 -54
  667. data/spec/unit/knife/user_list_spec.rb +73 -73
  668. data/spec/unit/knife/user_password_spec.rb +64 -64
  669. data/spec/unit/knife/user_reregister_spec.rb +56 -56
  670. data/spec/unit/knife/user_show_spec.rb +91 -91
  671. data/spec/unit/knife_spec.rb +637 -637
  672. data/spec/unit/utils/licensing_handler_spec.rb +140 -0
  673. metadata +11 -7
@@ -1,637 +1,637 @@
1
- #
2
- # Author:: Adam Jacob (<adam@chef.io>)
3
- # Author:: Tim Hinderliter (<tim@chef.io>)
4
- # Copyright:: Copyright (c) Chef Software Inc.
5
- # License:: Apache License, Version 2.0
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
- #
19
-
20
- # Fixtures for subcommand loading live in this namespace
21
- module KnifeSpecs
22
- end
23
-
24
- require "knife_spec_helper"
25
- require "uri"
26
- require "chef/knife/core/gem_glob_loader"
27
-
28
- describe Chef::Knife do
29
-
30
- let(:stderr) { StringIO.new }
31
-
32
- let(:knife) { Chef::Knife.new }
33
-
34
- let(:config_location) { File.expand_path("~/.chef/config.rb") }
35
-
36
- let(:config_loader) do
37
- instance_double("WorkstationConfigLoader",
38
- load: nil, no_config_found?: false,
39
- config_location: config_location,
40
- chef_config_dir: "/etc/chef")
41
- end
42
-
43
- before(:each) do
44
- Chef::Log.logger = Logger.new(StringIO.new)
45
-
46
- Chef::Config[:node_name] = "webmonkey.example.com"
47
-
48
- allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
49
- allow(config_loader).to receive(:explicit_config_file=)
50
- allow(config_loader).to receive(:profile=)
51
-
52
- # Prevent gratuitous code reloading:
53
- allow(Chef::Knife).to receive(:load_commands)
54
- allow(knife.ui).to receive(:puts)
55
- allow(knife.ui).to receive(:print)
56
- allow(Chef::Log).to receive(:init)
57
- allow(Chef::Log).to receive(:level)
58
- %i{debug info warn error crit}.each do |level_sym|
59
- allow(Chef::Log).to receive(level_sym)
60
- end
61
- allow(Chef::Knife).to receive(:puts)
62
- end
63
-
64
- after(:each) do
65
- Chef::Knife.reset_config_loader!
66
- end
67
-
68
- it "does not reset Chef::Config[:verbosity to nil if config[:verbosity] is nil" do
69
- Chef::Config[:verbosity] = 2
70
- Chef::Knife.new
71
- expect(Chef::Config[:verbosity]).to eq(2)
72
- end
73
-
74
- describe "after loading a subcommand" do
75
- before do
76
- Chef::Knife.reset_subcommands!
77
-
78
- if KnifeSpecs.const_defined?(:TestNameMapping)
79
- KnifeSpecs.send(:remove_const, :TestNameMapping)
80
- end
81
-
82
- if KnifeSpecs.const_defined?(:TestExplicitCategory)
83
- KnifeSpecs.send(:remove_const, :TestExplicitCategory)
84
- end
85
-
86
- Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_name_mapping.rb"))
87
- Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_explicit_category.rb"))
88
- end
89
-
90
- it "has a category based on its name" do
91
- expect(KnifeSpecs::TestNameMapping.subcommand_category).to eq("test")
92
- end
93
-
94
- it "has an explicitly defined category if set" do
95
- expect(KnifeSpecs::TestExplicitCategory.subcommand_category).to eq("cookbook site")
96
- end
97
-
98
- it "can reference the subcommand by its snake cased name" do
99
- expect(Chef::Knife.subcommands["test_name_mapping"]).to equal(KnifeSpecs::TestNameMapping)
100
- end
101
-
102
- it "lists subcommands by category" do
103
- expect(Chef::Knife.subcommands_by_category["test"]).to include("test_name_mapping")
104
- end
105
-
106
- it "lists subcommands by category when the subcommands have explicit categories" do
107
- expect(Chef::Knife.subcommands_by_category["cookbook site"]).to include("test_explicit_category")
108
- end
109
-
110
- it "has empty dependency_loader list by default" do
111
- expect(KnifeSpecs::TestNameMapping.dependency_loaders).to be_empty
112
- end
113
- end
114
-
115
- describe "after loading all subcommands" do
116
- before do
117
- Chef::Knife.reset_subcommands!
118
- Chef::Knife.load_commands
119
- end
120
-
121
- it "references a subcommand class by its snake cased name" do
122
- class SuperAwesomeCommand < Chef::Knife
123
- end
124
-
125
- Chef::Knife.load_commands
126
-
127
- expect(Chef::Knife.subcommands).to have_key("super_awesome_command")
128
- expect(Chef::Knife.subcommands["super_awesome_command"]).to eq(SuperAwesomeCommand)
129
- end
130
-
131
- it "records the location of ChefFS-based commands correctly" do
132
- class AwesomeCheffsCommand < Chef::ChefFS::Knife
133
- end
134
-
135
- Chef::Knife.load_commands
136
- expect(Chef::Knife.subcommand_files["awesome_cheffs_command"]).to eq([__FILE__])
137
- end
138
-
139
- it "guesses a category from a given ARGV" do
140
- Chef::Knife.subcommands_by_category["cookbook"] << :cookbook
141
- Chef::Knife.subcommands_by_category["cookbook site"] << :cookbook_site
142
- expect(Chef::Knife.guess_category(%w{cookbook foo bar baz})).to eq("cookbook")
143
- expect(Chef::Knife.guess_category(%w{cookbook site foo bar baz})).to eq("cookbook site")
144
- expect(Chef::Knife.guess_category(%w{cookbook site --help})).to eq("cookbook site")
145
- end
146
-
147
- it "finds a subcommand class based on ARGV" do
148
- Chef::Knife.subcommands["cookbook_site_install"] = :CookbookSiteInstall
149
- Chef::Knife.subcommands["cookbook"] = :Cookbook
150
- expect(Chef::Knife.subcommand_class_from(%w{cookbook site install --help foo bar baz})).to eq(:CookbookSiteInstall)
151
- end
152
-
153
- it "special case sets the subcommand_loader to GemGlobLoader when running rehash" do
154
- Chef::Knife.subcommands["rehash"] = :Rehash
155
- expect(Chef::Knife.subcommand_class_from(%w{rehash })).to eq(:Rehash)
156
- expect(Chef::Knife.subcommand_loader).to be_a(Chef::Knife::SubcommandLoader::GemGlobLoader)
157
- end
158
-
159
- end
160
-
161
- describe "the headers include X-Remote-Request-Id" do
162
-
163
- let(:headers) do
164
- { "Accept" => "application/json",
165
- "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
166
- "X-Chef-Version" => Chef::VERSION,
167
- "Host" => "api.opscode.piab",
168
- "X-REMOTE-REQUEST-ID" => request_id,
169
- }
170
- end
171
-
172
- let(:request_id) { "1234" }
173
-
174
- let(:request_mock) { {} }
175
-
176
- let(:rest) do
177
- allow(Net::HTTP).to receive(:new).and_return(http_client)
178
- allow(Chef::RequestID.instance).to receive(:request_id).and_return(request_id)
179
- allow(Chef::Config).to receive(:chef_server_url).and_return("https://api.opscode.piab")
180
- command = Chef::Knife.run(%w{test yourself})
181
- rest = command.noauth_rest
182
- rest
183
- end
184
-
185
- let!(:http_client) do
186
- http_client = Net::HTTP.new(url.host, url.port)
187
- allow(http_client).to receive(:request).and_yield(http_response).and_return(http_response)
188
- http_client
189
- end
190
-
191
- let(:url) { URI.parse("https://api.opscode.piab") }
192
-
193
- let(:http_response) do
194
- http_response = Net::HTTPSuccess.new("1.1", "200", "successful rest req")
195
- allow(http_response).to receive(:read_body)
196
- allow(http_response).to receive(:body).and_return(body)
197
- http_response["Content-Length"] = body.bytesize.to_s
198
- http_response
199
- end
200
-
201
- let(:body) { "ninja" }
202
-
203
- before(:each) do
204
- Chef::Config[:chef_server_url] = "https://api.opscode.piab"
205
- if KnifeSpecs.const_defined?(:TestYourself)
206
- KnifeSpecs.send :remove_const, :TestYourself
207
- end
208
- Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_yourself.rb"))
209
- Chef::Knife.subcommands.each { |name, klass| Chef::Knife.subcommands.delete(name) unless klass.is_a?(Class) }
210
- end
211
-
212
- it "confirms that the headers include X-Remote-Request-Id" do
213
- expect(Net::HTTP::Get).to receive(:new).with("/monkey", headers).and_return(request_mock)
214
- rest.get("monkey")
215
- end
216
- end
217
-
218
- describe "when running a command" do
219
- before(:each) do
220
- if KnifeSpecs.const_defined?(:TestYourself)
221
- KnifeSpecs.send :remove_const, :TestYourself
222
- end
223
- Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_yourself.rb"))
224
- Chef::Knife.subcommands.each { |name, klass| Chef::Knife.subcommands.delete(name) unless klass.is_a?(Class) }
225
- end
226
-
227
- it "merges the global knife CLI options" do
228
- extra_opts = {}
229
- extra_opts[:editor] = { long: "--editor EDITOR",
230
- description: "Set the editor to use for interactive commands",
231
- short: "-e EDITOR",
232
- default: "/usr/bin/vim" }
233
-
234
- # there is special hackery to return the subcommand instance going on here.
235
- command = Chef::Knife.run(%w{test yourself}, extra_opts)
236
- editor_opts = command.options[:editor]
237
- expect(editor_opts[:long]).to eq("--editor EDITOR")
238
- expect(editor_opts[:description]).to eq("Set the editor to use for interactive commands")
239
- expect(editor_opts[:short]).to eq("-e EDITOR")
240
- expect(editor_opts[:default]).to eq("/usr/bin/vim")
241
- end
242
-
243
- it "creates an instance of the subcommand and runs it" do
244
- command = Chef::Knife.run(%w{test yourself})
245
- expect(command).to be_an_instance_of(KnifeSpecs::TestYourself)
246
- expect(command.ran).to be_truthy
247
- end
248
-
249
- it "passes the command specific args to the subcommand" do
250
- command = Chef::Knife.run(%w{test yourself with some args})
251
- expect(command.name_args).to eq(%w{with some args})
252
- end
253
-
254
- it "excludes the command name from the name args when parts are joined with underscores" do
255
- command = Chef::Knife.run(%w{test_yourself with some args})
256
- expect(command.name_args).to eq(%w{with some args})
257
- end
258
-
259
- it "exits if no subcommand matches the CLI args" do
260
- stdout = StringIO.new
261
-
262
- allow(Chef::Knife.ui).to receive(:stderr).and_return(stderr)
263
- allow(Chef::Knife.ui).to receive(:stdout).and_return(stdout)
264
- expect(Chef::Knife.ui).to receive(:fatal)
265
- expect { Chef::Knife.run(%w{fuuu uuuu fuuuu}) }.to raise_error(SystemExit) { |e| expect(e.status).not_to eq(0) }
266
- end
267
-
268
- it "loads lazy dependencies" do
269
- Chef::Knife.run(%w{test yourself})
270
- expect(KnifeSpecs::TestYourself.test_deps_loaded).to be_truthy
271
- end
272
-
273
- it "loads lazy dependencies from multiple deps calls" do
274
- other_deps_loaded = false
275
- KnifeSpecs::TestYourself.class_eval do
276
- deps { other_deps_loaded = true }
277
- end
278
-
279
- Chef::Knife.run(%w{test yourself})
280
- expect(KnifeSpecs::TestYourself.test_deps_loaded).to be_truthy
281
- expect(other_deps_loaded).to be_truthy
282
- end
283
-
284
- describe "working with unmerged configuration in #config_source" do
285
- let(:command) { KnifeSpecs::TestYourself.new([]) }
286
-
287
- before do
288
- KnifeSpecs::TestYourself.option(:opt_with_default,
289
- short: "-D VALUE",
290
- default: "default-value")
291
- end
292
- # This supports a use case used by plugins, where the pattern
293
- # seems to follow:
294
- # cmd = KnifeCommand.new
295
- # cmd.config[:config_key] = value
296
- # cmd.run
297
- #
298
- # This bypasses Knife::run and the `merge_configs` call it
299
- # performs - config_source should break when that happens.
300
- context "when config is fed in directly without a merge" do
301
- it "retains the value but returns nil as a config source" do
302
- command.config[:test1] = "value"
303
- expect(command.config[:test1]).to eq "value"
304
- expect(command.config_source(:test1)).to eq nil
305
- end
306
- end
307
-
308
- end
309
- describe "merging configuration options" do
310
- before do
311
- KnifeSpecs::TestYourself.option(:opt_with_default,
312
- short: "-D VALUE",
313
- default: "default-value")
314
- end
315
-
316
- it "sets the default log_location to STDERR for Chef::Log warnings" do
317
- knife_command = KnifeSpecs::TestYourself.new([])
318
- knife_command.configure_chef
319
- expect(Chef::Config[:log_location]).to eq(STDERR)
320
- end
321
-
322
- it "sets the default log_level to warn so we can issue Chef::Log.warn" do
323
- # Reset the log level to the default value
324
- Chef::Config[:log_level] = :auto
325
-
326
- knife_command = KnifeSpecs::TestYourself.new([])
327
- knife_command.configure_chef
328
- expect(Chef::Config[:log_level]).to eql(:warn)
329
- end
330
-
331
- it "prefers the default value from option definition if no config or command line value is present and reports the source as default" do
332
- knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
333
- knife_command.configure_chef
334
- expect(knife_command.config[:opt_with_default]).to eq("default-value")
335
- expect(knife_command.config_source(:opt_with_default)).to eq(:cli_default)
336
- end
337
-
338
- it "prefers a value in Chef::Config[:knife] to the default and reports the source as config" do
339
- Chef::Config[:knife][:opt_with_default] = "from-knife-config"
340
- knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
341
- knife_command.configure_chef
342
- expect(knife_command.config[:opt_with_default]).to eq("from-knife-config")
343
- expect(knife_command.config_source(:opt_with_default)).to eq(:config)
344
- end
345
-
346
- it "prefers a value from command line over Chef::Config and the default and reports the source as CLI" do
347
- knife_command = KnifeSpecs::TestYourself.new(["-D", "from-cli"])
348
- knife_command.configure_chef
349
- expect(knife_command.config[:opt_with_default]).to eq("from-cli")
350
- expect(knife_command.config_source(:opt_with_default)).to eq(:cli)
351
- end
352
-
353
- it "merges `listen` config to Chef::Config" do
354
- knife_command = Chef::Knife.run(%w{test yourself --no-listen}, Chef::Application::Knife.options)
355
- expect(Chef::Config[:listen]).to be(false)
356
- expect(knife_command.config_source(:listen)).to eq(:cli)
357
- end
358
-
359
- it "merges Chef::Config[:knife] values into the config hash even if they have no cli keys" do
360
- Chef::Config[:knife][:opt_with_no_cli_key] = "from-knife-config"
361
- knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
362
- knife_command.configure_chef
363
- expect(knife_command.config[:opt_with_no_cli_key]).to eq("from-knife-config")
364
- expect(knife_command.config_source(:opt_with_no_cli_key)).to eq(:config)
365
- end
366
-
367
- it "merges Chef::Config[:knife] default values into the config hash even if they have no cli keys" do
368
- Chef::Config.config_context :knife do
369
- default :opt_with_no_cli_key, "from-knife-default"
370
- end
371
- knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
372
- knife_command.configure_chef
373
- expect(knife_command.config[:opt_with_no_cli_key]).to eq("from-knife-default")
374
- expect(knife_command.config_source(:opt_with_no_cli_key)).to eq(:config_default)
375
- end
376
-
377
- context "verbosity is one" do
378
- let(:fake_config) { "/does/not/exist/knife.rb" }
379
-
380
- before do
381
- knife.config[:verbosity] = 1
382
- knife.config[:config_file] = fake_config
383
- config_loader = double("Chef::WorkstationConfigLoader", load: true, no_config_found?: false, chef_config_dir: "/etc/chef", config_location: fake_config)
384
- allow(config_loader).to receive(:explicit_config_file=).with(fake_config).and_return(fake_config)
385
- allow(config_loader).to receive(:profile=)
386
- allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
387
- end
388
-
389
- it "prints the path to the configuration file used" do
390
- stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
391
- knife.ui = Chef::Knife::UI.new(stdout, stderr, stdin, {})
392
- expect(Chef::Log).to receive(:info).with("Using configuration from #{fake_config}")
393
- knife.configure_chef
394
- end
395
- end
396
-
397
- # -VV (2) is debug, -VVV (3) is trace
398
- [ 2, 3 ].each do |verbosity|
399
- it "does not humanize the exception if Chef::Config[:verbosity] is #{verbosity}" do
400
- Chef::Config[:verbosity] = verbosity
401
- allow(knife).to receive(:run).and_raise(Exception)
402
- expect(knife).not_to receive(:humanize_exception)
403
- expect { knife.run_with_pretty_exceptions }.to raise_error(Exception)
404
- end
405
- end
406
- end
407
-
408
- describe "setting arbitrary configuration with --config-option" do
409
-
410
- let(:stdout) { StringIO.new }
411
-
412
- let(:stderr) { StringIO.new }
413
-
414
- let(:stdin) { StringIO.new }
415
-
416
- let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, disable_editing: true) }
417
-
418
- let(:subcommand) do
419
- KnifeSpecs::TestYourself.options = Chef::Application::Knife.options.merge(KnifeSpecs::TestYourself.options)
420
- KnifeSpecs::TestYourself.new(%w{--config-option badly_formatted_arg}).tap do |cmd|
421
- cmd.ui = ui
422
- end
423
- end
424
-
425
- it "sets arbitrary configuration via --config-option" do
426
- Chef::Knife.run(%w{test yourself --config-option arbitrary_config_thing=hello}, Chef::Application::Knife.options)
427
- expect(Chef::Config[:arbitrary_config_thing]).to eq("hello")
428
- end
429
-
430
- it "handles errors in arbitrary configuration" do
431
- expect(subcommand).to receive(:exit).with(1)
432
- subcommand.configure_chef
433
- expect(stderr.string).to include("ERROR: Unparsable config option \"badly_formatted_arg\"")
434
- expect(stdout.string).to include(subcommand.opt_parser.to_s)
435
- end
436
- end
437
-
438
- end
439
-
440
- describe "when first created" do
441
-
442
- let(:knife) {
443
- Kernel.load "spec/data/knife_subcommand/test_yourself.rb"
444
- KnifeSpecs::TestYourself.new(%w{with some args -s scrogramming})
445
- }
446
-
447
- it "it parses the options passed to it" do
448
- expect(knife.config[:scro]).to eq("scrogramming")
449
- end
450
-
451
- it "extracts its command specific args from the full arg list" do
452
- expect(knife.name_args).to eq(%w{with some args})
453
- end
454
-
455
- it "does not have lazy dependencies loaded" do
456
- skip "unstable with randomization... prolly needs more isolation"
457
-
458
- expect(knife.class.test_deps_loaded).not_to be_truthy
459
- end
460
- end
461
-
462
- describe "when formatting exceptions" do
463
-
464
- let(:stdout) { StringIO.new }
465
- let(:stderr) { StringIO.new }
466
- let(:stdin) { StringIO.new }
467
-
468
- let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) }
469
-
470
- before do
471
- knife.ui = ui
472
- expect(knife).to receive(:exit).with(100)
473
- end
474
-
475
- it "formats 401s nicely" do
476
- response = Net::HTTPUnauthorized.new("1.1", "401", "Unauthorized")
477
- response.instance_variable_set(:@read, true) # I hate you, net/http.
478
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u no syncronize your clock?"))
479
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("401 Unauthorized", response))
480
- knife.run_with_pretty_exceptions
481
- expect(stderr.string).to match(/ERROR: Failed to authenticate to/)
482
- expect(stderr.string).to match(/Response: y u no syncronize your clock\?/)
483
- end
484
-
485
- it "formats 403s nicely" do
486
- response = Net::HTTPForbidden.new("1.1", "403", "Forbidden")
487
- response.instance_variable_set(:@read, true) # I hate you, net/http.
488
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u no administrator"))
489
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("403 Forbidden", response))
490
- allow(knife).to receive(:username).and_return("sadpanda")
491
- knife.run_with_pretty_exceptions
492
- expect(stderr.string).to match(/ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action/)
493
- expect(stderr.string).to match(/Response: y u no administrator/)
494
- end
495
-
496
- context "when proxy servers are set" do
497
- before do
498
- ENV["http_proxy"] = "xyz"
499
- end
500
-
501
- after do
502
- ENV.delete("http_proxy")
503
- end
504
-
505
- it "formats proxy errors nicely" do
506
- response = Net::HTTPForbidden.new("1.1", "403", "Forbidden")
507
- response.instance_variable_set(:@read, true)
508
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u no administrator"))
509
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("403 Forbidden", response))
510
- allow(knife).to receive(:username).and_return("sadpanda")
511
- knife.run_with_pretty_exceptions
512
- expect(stderr.string).to match(/ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action/)
513
- expect(stderr.string).to match(/ERROR: There are proxy servers configured, your server url may need to be added to NO_PROXY./)
514
- expect(stderr.string).to match(/Response: y u no administrator/)
515
- end
516
- end
517
-
518
- it "formats 400s nicely" do
519
- response = Net::HTTPBadRequest.new("1.1", "400", "Bad Request")
520
- response.instance_variable_set(:@read, true) # I hate you, net/http.
521
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u search wrong"))
522
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("400 Bad Request", response))
523
- knife.run_with_pretty_exceptions
524
- expect(stderr.string).to match(/ERROR: The data in your request was invalid/)
525
- expect(stderr.string).to match(/Response: y u search wrong/)
526
- end
527
-
528
- it "formats 404s nicely" do
529
- response = Net::HTTPNotFound.new("1.1", "404", "Not Found")
530
- response.instance_variable_set(:@read, true) # I hate you, net/http.
531
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "nothing to see here"))
532
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("404 Not Found", response))
533
- knife.run_with_pretty_exceptions
534
- expect(stderr.string).to match(/ERROR: The object you are looking for could not be found/)
535
- expect(stderr.string).to match(/Response: nothing to see here/)
536
- end
537
-
538
- it "formats 406s (non-supported API version error) nicely" do
539
- response = Net::HTTPNotAcceptable.new("1.1", "406", "Not Acceptable")
540
- response.instance_variable_set(:@read, true) # I hate you, net/http.
541
-
542
- # set the header
543
- response["x-ops-server-api-version"] = Chef::JSONCompat.to_json(min_version: "0", max_version: "1", request_version: "10000000")
544
-
545
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "sad trombone"))
546
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("406 Not Acceptable", response))
547
-
548
- knife.run_with_pretty_exceptions
549
- expect(stderr.string).to match(/The request that .* sent was using API version 10000000./)
550
- expect(stderr.string).to match(/The server you sent the request to supports a min API version of 0 and a max API version of 1./)
551
- expect(stderr.string).to match(/Please either update your .* or the server to be a compatible set./)
552
- end
553
-
554
- it "formats 500s nicely" do
555
- response = Net::HTTPInternalServerError.new("1.1", "500", "Internal Server Error")
556
- response.instance_variable_set(:@read, true) # I hate you, net/http.
557
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "sad trombone"))
558
- allow(knife).to receive(:run).and_raise(Net::HTTPFatalError.new("500 Internal Server Error", response))
559
- knife.run_with_pretty_exceptions
560
- expect(stderr.string).to match(/ERROR: internal server error/)
561
- expect(stderr.string).to match(/Response: sad trombone/)
562
- end
563
-
564
- it "formats 502s nicely" do
565
- response = Net::HTTPBadGateway.new("1.1", "502", "Bad Gateway")
566
- response.instance_variable_set(:@read, true) # I hate you, net/http.
567
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "sadder trombone"))
568
- allow(knife).to receive(:run).and_raise(Net::HTTPFatalError.new("502 Bad Gateway", response))
569
- knife.run_with_pretty_exceptions
570
- expect(stderr.string).to match(/ERROR: bad gateway/)
571
- expect(stderr.string).to match(/Response: sadder trombone/)
572
- end
573
-
574
- it "formats 503s nicely" do
575
- response = Net::HTTPServiceUnavailable.new("1.1", "503", "Service Unavailable")
576
- response.instance_variable_set(:@read, true) # I hate you, net/http.
577
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "saddest trombone"))
578
- allow(knife).to receive(:run).and_raise(Net::HTTPFatalError.new("503 Service Unavailable", response))
579
- knife.run_with_pretty_exceptions
580
- expect(stderr.string).to match(/ERROR: Service temporarily unavailable/)
581
- expect(stderr.string).to match(/Response: saddest trombone/)
582
- end
583
-
584
- it "formats other HTTP errors nicely" do
585
- response = Net::HTTPPaymentRequired.new("1.1", "402", "Payment Required")
586
- response.instance_variable_set(:@read, true) # I hate you, net/http.
587
- allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "nobugfixtillyoubuy"))
588
- allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("402 Payment Required", response))
589
- knife.run_with_pretty_exceptions
590
- expect(stderr.string).to match(/ERROR: Payment Required/)
591
- expect(stderr.string).to match(/Response: nobugfixtillyoubuy/)
592
- end
593
-
594
- it "formats NameError and NoMethodError nicely" do
595
- allow(knife).to receive(:run).and_raise(NameError.new("Undefined constant FUUU"))
596
- knife.run_with_pretty_exceptions
597
- expect(stderr.string).to match(/ERROR: .* encountered an unexpected error/)
598
- expect(stderr.string).to match(/This may be a bug in the 'knife' .* command or plugin/)
599
- expect(stderr.string).to match(/Exception: NameError: Undefined constant FUUU/)
600
- end
601
-
602
- it "formats missing private key errors nicely" do
603
- allow(knife).to receive(:run).and_raise(Chef::Exceptions::PrivateKeyMissing.new("key not there"))
604
- allow(knife).to receive(:api_key).and_return("/home/root/.chef/no-key-here.pem")
605
- knife.run_with_pretty_exceptions
606
- expect(stderr.string).to match(%r{ERROR: Your private key could not be loaded from /home/root/.chef/no-key-here.pem})
607
- expect(stderr.string).to match(/Check your configuration file and ensure that your private key is readable/)
608
- end
609
-
610
- it "formats connection refused errors nicely" do
611
- allow(knife).to receive(:run).and_raise(Errno::ECONNREFUSED.new("y u no shut up"))
612
- knife.run_with_pretty_exceptions
613
- # Errno::ECONNREFUSED message differs by platform
614
- # *nix = Errno::ECONNREFUSED: Connection refused
615
- # win32: Errno::ECONNREFUSED: No connection could be made because the target machine actively refused it.
616
- expect(stderr.string).to match(/ERROR: Network Error: .* - y u no shut up/)
617
- expect(stderr.string).to match(/Check your .* configuration and network settings/)
618
- end
619
-
620
- it "formats SSL errors nicely and suggests to use `knife ssl check` and `knife ssl fetch`" do
621
- error = OpenSSL::SSL::SSLError.new("SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed")
622
- allow(knife).to receive(:run).and_raise(error)
623
-
624
- knife.run_with_pretty_exceptions
625
-
626
- expected_message = <<~MSG
627
- ERROR: Could not establish a secure connection to the server.
628
- Use `.* ssl check` to troubleshoot your SSL configuration.
629
- If your server uses a self-signed certificate, you can use
630
- `.* ssl fetch` to make .* trust the server's certificates.
631
- MSG
632
- expect(stderr.string).to match(expected_message)
633
- end
634
-
635
- end
636
-
637
- end
1
+ #
2
+ # Author:: Adam Jacob (<adam@chef.io>)
3
+ # Author:: Tim Hinderliter (<tim@chef.io>)
4
+ # Copyright:: Copyright (c) Chef Software Inc.
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ # Fixtures for subcommand loading live in this namespace
21
+ module KnifeSpecs
22
+ end
23
+
24
+ require "knife_spec_helper"
25
+ require "uri"
26
+ require "chef/knife/core/gem_glob_loader"
27
+
28
+ describe Chef::Knife do
29
+
30
+ let(:stderr) { StringIO.new }
31
+
32
+ let(:knife) { Chef::Knife.new }
33
+
34
+ let(:config_location) { File.expand_path("~/.chef/config.rb") }
35
+
36
+ let(:config_loader) do
37
+ instance_double("WorkstationConfigLoader",
38
+ load: nil, no_config_found?: false,
39
+ config_location: config_location,
40
+ chef_config_dir: "/etc/chef")
41
+ end
42
+
43
+ before(:each) do
44
+ Chef::Log.logger = Logger.new(StringIO.new)
45
+
46
+ Chef::Config[:node_name] = "webmonkey.example.com"
47
+
48
+ allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
49
+ allow(config_loader).to receive(:explicit_config_file=)
50
+ allow(config_loader).to receive(:profile=)
51
+
52
+ # Prevent gratuitous code reloading:
53
+ allow(Chef::Knife).to receive(:load_commands)
54
+ allow(knife.ui).to receive(:puts)
55
+ allow(knife.ui).to receive(:print)
56
+ allow(Chef::Log).to receive(:init)
57
+ allow(Chef::Log).to receive(:level)
58
+ %i{debug info warn error crit}.each do |level_sym|
59
+ allow(Chef::Log).to receive(level_sym)
60
+ end
61
+ allow(Chef::Knife).to receive(:puts)
62
+ end
63
+
64
+ after(:each) do
65
+ Chef::Knife.reset_config_loader!
66
+ end
67
+
68
+ it "does not reset Chef::Config[:verbosity to nil if config[:verbosity] is nil" do
69
+ Chef::Config[:verbosity] = 2
70
+ Chef::Knife.new
71
+ expect(Chef::Config[:verbosity]).to eq(2)
72
+ end
73
+
74
+ describe "after loading a subcommand" do
75
+ before do
76
+ Chef::Knife.reset_subcommands!
77
+
78
+ if KnifeSpecs.const_defined?(:TestNameMapping)
79
+ KnifeSpecs.send(:remove_const, :TestNameMapping)
80
+ end
81
+
82
+ if KnifeSpecs.const_defined?(:TestExplicitCategory)
83
+ KnifeSpecs.send(:remove_const, :TestExplicitCategory)
84
+ end
85
+
86
+ Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_name_mapping.rb"))
87
+ Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_explicit_category.rb"))
88
+ end
89
+
90
+ it "has a category based on its name" do
91
+ expect(KnifeSpecs::TestNameMapping.subcommand_category).to eq("test")
92
+ end
93
+
94
+ it "has an explicitly defined category if set" do
95
+ expect(KnifeSpecs::TestExplicitCategory.subcommand_category).to eq("cookbook site")
96
+ end
97
+
98
+ it "can reference the subcommand by its snake cased name" do
99
+ expect(Chef::Knife.subcommands["test_name_mapping"]).to equal(KnifeSpecs::TestNameMapping)
100
+ end
101
+
102
+ it "lists subcommands by category" do
103
+ expect(Chef::Knife.subcommands_by_category["test"]).to include("test_name_mapping")
104
+ end
105
+
106
+ it "lists subcommands by category when the subcommands have explicit categories" do
107
+ expect(Chef::Knife.subcommands_by_category["cookbook site"]).to include("test_explicit_category")
108
+ end
109
+
110
+ it "has empty dependency_loader list by default" do
111
+ expect(KnifeSpecs::TestNameMapping.dependency_loaders).to be_empty
112
+ end
113
+ end
114
+
115
+ describe "after loading all subcommands" do
116
+ before do
117
+ Chef::Knife.reset_subcommands!
118
+ Chef::Knife.load_commands
119
+ end
120
+
121
+ it "references a subcommand class by its snake cased name" do
122
+ class SuperAwesomeCommand < Chef::Knife
123
+ end
124
+
125
+ Chef::Knife.load_commands
126
+
127
+ expect(Chef::Knife.subcommands).to have_key("super_awesome_command")
128
+ expect(Chef::Knife.subcommands["super_awesome_command"]).to eq(SuperAwesomeCommand)
129
+ end
130
+
131
+ it "records the location of ChefFS-based commands correctly" do
132
+ class AwesomeCheffsCommand < Chef::ChefFS::Knife
133
+ end
134
+
135
+ Chef::Knife.load_commands
136
+ expect(Chef::Knife.subcommand_files["awesome_cheffs_command"]).to eq([__FILE__])
137
+ end
138
+
139
+ it "guesses a category from a given ARGV" do
140
+ Chef::Knife.subcommands_by_category["cookbook"] << :cookbook
141
+ Chef::Knife.subcommands_by_category["cookbook site"] << :cookbook_site
142
+ expect(Chef::Knife.guess_category(%w{cookbook foo bar baz})).to eq("cookbook")
143
+ expect(Chef::Knife.guess_category(%w{cookbook site foo bar baz})).to eq("cookbook site")
144
+ expect(Chef::Knife.guess_category(%w{cookbook site --help})).to eq("cookbook site")
145
+ end
146
+
147
+ it "finds a subcommand class based on ARGV" do
148
+ Chef::Knife.subcommands["cookbook_site_install"] = :CookbookSiteInstall
149
+ Chef::Knife.subcommands["cookbook"] = :Cookbook
150
+ expect(Chef::Knife.subcommand_class_from(%w{cookbook site install --help foo bar baz})).to eq(:CookbookSiteInstall)
151
+ end
152
+
153
+ it "special case sets the subcommand_loader to GemGlobLoader when running rehash" do
154
+ Chef::Knife.subcommands["rehash"] = :Rehash
155
+ expect(Chef::Knife.subcommand_class_from(%w{rehash })).to eq(:Rehash)
156
+ expect(Chef::Knife.subcommand_loader).to be_a(Chef::Knife::SubcommandLoader::GemGlobLoader)
157
+ end
158
+
159
+ end
160
+
161
+ describe "the headers include X-Remote-Request-Id" do
162
+
163
+ let(:headers) do
164
+ { "Accept" => "application/json",
165
+ "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
166
+ "X-Chef-Version" => Chef::VERSION,
167
+ "Host" => "api.opscode.piab",
168
+ "X-REMOTE-REQUEST-ID" => request_id,
169
+ }
170
+ end
171
+
172
+ let(:request_id) { "1234" }
173
+
174
+ let(:request_mock) { {} }
175
+
176
+ let(:rest) do
177
+ allow(Net::HTTP).to receive(:new).and_return(http_client)
178
+ allow(Chef::RequestID.instance).to receive(:request_id).and_return(request_id)
179
+ allow(Chef::Config).to receive(:chef_server_url).and_return("https://api.opscode.piab")
180
+ command = Chef::Knife.run(%w{test yourself})
181
+ rest = command.noauth_rest
182
+ rest
183
+ end
184
+
185
+ let!(:http_client) do
186
+ http_client = Net::HTTP.new(url.host, url.port)
187
+ allow(http_client).to receive(:request).and_yield(http_response).and_return(http_response)
188
+ http_client
189
+ end
190
+
191
+ let(:url) { URI.parse("https://api.opscode.piab") }
192
+
193
+ let(:http_response) do
194
+ http_response = Net::HTTPSuccess.new("1.1", "200", "successful rest req")
195
+ allow(http_response).to receive(:read_body)
196
+ allow(http_response).to receive(:body).and_return(body)
197
+ http_response["Content-Length"] = body.bytesize.to_s
198
+ http_response
199
+ end
200
+
201
+ let(:body) { "ninja" }
202
+
203
+ before(:each) do
204
+ Chef::Config[:chef_server_url] = "https://api.opscode.piab"
205
+ if KnifeSpecs.const_defined?(:TestYourself)
206
+ KnifeSpecs.send :remove_const, :TestYourself
207
+ end
208
+ Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_yourself.rb"))
209
+ Chef::Knife.subcommands.each { |name, klass| Chef::Knife.subcommands.delete(name) unless klass.is_a?(Class) }
210
+ end
211
+
212
+ it "confirms that the headers include X-Remote-Request-Id" do
213
+ expect(Net::HTTP::Get).to receive(:new).with("/monkey", headers).and_return(request_mock)
214
+ rest.get("monkey")
215
+ end
216
+ end
217
+
218
+ describe "when running a command" do
219
+ before(:each) do
220
+ if KnifeSpecs.const_defined?(:TestYourself)
221
+ KnifeSpecs.send :remove_const, :TestYourself
222
+ end
223
+ Kernel.load(File.join(CHEF_SPEC_DATA, "knife_subcommand", "test_yourself.rb"))
224
+ Chef::Knife.subcommands.each { |name, klass| Chef::Knife.subcommands.delete(name) unless klass.is_a?(Class) }
225
+ end
226
+
227
+ it "merges the global knife CLI options" do
228
+ extra_opts = {}
229
+ extra_opts[:editor] = { long: "--editor EDITOR",
230
+ description: "Set the editor to use for interactive commands",
231
+ short: "-e EDITOR",
232
+ default: "/usr/bin/vim" }
233
+
234
+ # there is special hackery to return the subcommand instance going on here.
235
+ command = Chef::Knife.run(%w{test yourself}, extra_opts)
236
+ editor_opts = command.options[:editor]
237
+ expect(editor_opts[:long]).to eq("--editor EDITOR")
238
+ expect(editor_opts[:description]).to eq("Set the editor to use for interactive commands")
239
+ expect(editor_opts[:short]).to eq("-e EDITOR")
240
+ expect(editor_opts[:default]).to eq("/usr/bin/vim")
241
+ end
242
+
243
+ it "creates an instance of the subcommand and runs it" do
244
+ command = Chef::Knife.run(%w{test yourself})
245
+ expect(command).to be_an_instance_of(KnifeSpecs::TestYourself)
246
+ expect(command.ran).to be_truthy
247
+ end
248
+
249
+ it "passes the command specific args to the subcommand" do
250
+ command = Chef::Knife.run(%w{test yourself with some args})
251
+ expect(command.name_args).to eq(%w{with some args})
252
+ end
253
+
254
+ it "excludes the command name from the name args when parts are joined with underscores" do
255
+ command = Chef::Knife.run(%w{test_yourself with some args})
256
+ expect(command.name_args).to eq(%w{with some args})
257
+ end
258
+
259
+ it "exits if no subcommand matches the CLI args" do
260
+ stdout = StringIO.new
261
+
262
+ allow(Chef::Knife.ui).to receive(:stderr).and_return(stderr)
263
+ allow(Chef::Knife.ui).to receive(:stdout).and_return(stdout)
264
+ expect(Chef::Knife.ui).to receive(:fatal)
265
+ expect { Chef::Knife.run(%w{fuuu uuuu fuuuu}) }.to raise_error(SystemExit) { |e| expect(e.status).not_to eq(0) }
266
+ end
267
+
268
+ it "loads lazy dependencies" do
269
+ Chef::Knife.run(%w{test yourself})
270
+ expect(KnifeSpecs::TestYourself.test_deps_loaded).to be_truthy
271
+ end
272
+
273
+ it "loads lazy dependencies from multiple deps calls" do
274
+ other_deps_loaded = false
275
+ KnifeSpecs::TestYourself.class_eval do
276
+ deps { other_deps_loaded = true }
277
+ end
278
+
279
+ Chef::Knife.run(%w{test yourself})
280
+ expect(KnifeSpecs::TestYourself.test_deps_loaded).to be_truthy
281
+ expect(other_deps_loaded).to be_truthy
282
+ end
283
+
284
+ describe "working with unmerged configuration in #config_source" do
285
+ let(:command) { KnifeSpecs::TestYourself.new([]) }
286
+
287
+ before do
288
+ KnifeSpecs::TestYourself.option(:opt_with_default,
289
+ short: "-D VALUE",
290
+ default: "default-value")
291
+ end
292
+ # This supports a use case used by plugins, where the pattern
293
+ # seems to follow:
294
+ # cmd = KnifeCommand.new
295
+ # cmd.config[:config_key] = value
296
+ # cmd.run
297
+ #
298
+ # This bypasses Knife::run and the `merge_configs` call it
299
+ # performs - config_source should break when that happens.
300
+ context "when config is fed in directly without a merge" do
301
+ it "retains the value but returns nil as a config source" do
302
+ command.config[:test1] = "value"
303
+ expect(command.config[:test1]).to eq "value"
304
+ expect(command.config_source(:test1)).to eq nil
305
+ end
306
+ end
307
+
308
+ end
309
+ describe "merging configuration options" do
310
+ before do
311
+ KnifeSpecs::TestYourself.option(:opt_with_default,
312
+ short: "-D VALUE",
313
+ default: "default-value")
314
+ end
315
+
316
+ it "sets the default log_location to STDERR for Chef::Log warnings" do
317
+ knife_command = KnifeSpecs::TestYourself.new([])
318
+ knife_command.configure_chef
319
+ expect(Chef::Config[:log_location]).to eq(STDERR)
320
+ end
321
+
322
+ it "sets the default log_level to warn so we can issue Chef::Log.warn" do
323
+ # Reset the log level to the default value
324
+ Chef::Config[:log_level] = :auto
325
+
326
+ knife_command = KnifeSpecs::TestYourself.new([])
327
+ knife_command.configure_chef
328
+ expect(Chef::Config[:log_level]).to eql(:warn)
329
+ end
330
+
331
+ it "prefers the default value from option definition if no config or command line value is present and reports the source as default" do
332
+ knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
333
+ knife_command.configure_chef
334
+ expect(knife_command.config[:opt_with_default]).to eq("default-value")
335
+ expect(knife_command.config_source(:opt_with_default)).to eq(:cli_default)
336
+ end
337
+
338
+ it "prefers a value in Chef::Config[:knife] to the default and reports the source as config" do
339
+ Chef::Config[:knife][:opt_with_default] = "from-knife-config"
340
+ knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
341
+ knife_command.configure_chef
342
+ expect(knife_command.config[:opt_with_default]).to eq("from-knife-config")
343
+ expect(knife_command.config_source(:opt_with_default)).to eq(:config)
344
+ end
345
+
346
+ it "prefers a value from command line over Chef::Config and the default and reports the source as CLI" do
347
+ knife_command = KnifeSpecs::TestYourself.new(["-D", "from-cli"])
348
+ knife_command.configure_chef
349
+ expect(knife_command.config[:opt_with_default]).to eq("from-cli")
350
+ expect(knife_command.config_source(:opt_with_default)).to eq(:cli)
351
+ end
352
+
353
+ it "merges `listen` config to Chef::Config" do
354
+ knife_command = Chef::Knife.run(%w{test yourself --no-listen}, Chef::Application::Knife.options)
355
+ expect(Chef::Config[:listen]).to be(false)
356
+ expect(knife_command.config_source(:listen)).to eq(:cli)
357
+ end
358
+
359
+ it "merges Chef::Config[:knife] values into the config hash even if they have no cli keys" do
360
+ Chef::Config[:knife][:opt_with_no_cli_key] = "from-knife-config"
361
+ knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
362
+ knife_command.configure_chef
363
+ expect(knife_command.config[:opt_with_no_cli_key]).to eq("from-knife-config")
364
+ expect(knife_command.config_source(:opt_with_no_cli_key)).to eq(:config)
365
+ end
366
+
367
+ it "merges Chef::Config[:knife] default values into the config hash even if they have no cli keys" do
368
+ Chef::Config.config_context :knife do
369
+ default :opt_with_no_cli_key, "from-knife-default"
370
+ end
371
+ knife_command = KnifeSpecs::TestYourself.new([]) # empty argv
372
+ knife_command.configure_chef
373
+ expect(knife_command.config[:opt_with_no_cli_key]).to eq("from-knife-default")
374
+ expect(knife_command.config_source(:opt_with_no_cli_key)).to eq(:config_default)
375
+ end
376
+
377
+ context "verbosity is one" do
378
+ let(:fake_config) { "/does/not/exist/knife.rb" }
379
+
380
+ before do
381
+ knife.config[:verbosity] = 1
382
+ knife.config[:config_file] = fake_config
383
+ config_loader = double("Chef::WorkstationConfigLoader", load: true, no_config_found?: false, chef_config_dir: "/etc/chef", config_location: fake_config)
384
+ allow(config_loader).to receive(:explicit_config_file=).with(fake_config).and_return(fake_config)
385
+ allow(config_loader).to receive(:profile=)
386
+ allow(Chef::WorkstationConfigLoader).to receive(:new).and_return(config_loader)
387
+ end
388
+
389
+ it "prints the path to the configuration file used" do
390
+ stdout, stderr, stdin = StringIO.new, StringIO.new, StringIO.new
391
+ knife.ui = Chef::Knife::UI.new(stdout, stderr, stdin, {})
392
+ expect(Chef::Log).to receive(:info).with("Using configuration from #{fake_config}")
393
+ knife.configure_chef
394
+ end
395
+ end
396
+
397
+ # -VV (2) is debug, -VVV (3) is trace
398
+ [ 2, 3 ].each do |verbosity|
399
+ it "does not humanize the exception if Chef::Config[:verbosity] is #{verbosity}" do
400
+ Chef::Config[:verbosity] = verbosity
401
+ allow(knife).to receive(:run).and_raise(Exception)
402
+ expect(knife).not_to receive(:humanize_exception)
403
+ expect { knife.run_with_pretty_exceptions }.to raise_error(Exception)
404
+ end
405
+ end
406
+ end
407
+
408
+ describe "setting arbitrary configuration with --config-option" do
409
+
410
+ let(:stdout) { StringIO.new }
411
+
412
+ let(:stderr) { StringIO.new }
413
+
414
+ let(:stdin) { StringIO.new }
415
+
416
+ let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, disable_editing: true) }
417
+
418
+ let(:subcommand) do
419
+ KnifeSpecs::TestYourself.options = Chef::Application::Knife.options.merge(KnifeSpecs::TestYourself.options)
420
+ KnifeSpecs::TestYourself.new(%w{--config-option badly_formatted_arg}).tap do |cmd|
421
+ cmd.ui = ui
422
+ end
423
+ end
424
+
425
+ it "sets arbitrary configuration via --config-option" do
426
+ Chef::Knife.run(%w{test yourself --config-option arbitrary_config_thing=hello}, Chef::Application::Knife.options)
427
+ expect(Chef::Config[:arbitrary_config_thing]).to eq("hello")
428
+ end
429
+
430
+ it "handles errors in arbitrary configuration" do
431
+ expect(subcommand).to receive(:exit).with(1)
432
+ subcommand.configure_chef
433
+ expect(stderr.string).to include("ERROR: Unparsable config option \"badly_formatted_arg\"")
434
+ expect(stdout.string).to include(subcommand.opt_parser.to_s)
435
+ end
436
+ end
437
+
438
+ end
439
+
440
+ describe "when first created" do
441
+
442
+ let(:knife) {
443
+ Kernel.load "spec/data/knife_subcommand/test_yourself.rb"
444
+ KnifeSpecs::TestYourself.new(%w{with some args -s scrogramming})
445
+ }
446
+
447
+ it "it parses the options passed to it" do
448
+ expect(knife.config[:scro]).to eq("scrogramming")
449
+ end
450
+
451
+ it "extracts its command specific args from the full arg list" do
452
+ expect(knife.name_args).to eq(%w{with some args})
453
+ end
454
+
455
+ it "does not have lazy dependencies loaded" do
456
+ skip "unstable with randomization... prolly needs more isolation"
457
+
458
+ expect(knife.class.test_deps_loaded).not_to be_truthy
459
+ end
460
+ end
461
+
462
+ describe "when formatting exceptions" do
463
+
464
+ let(:stdout) { StringIO.new }
465
+ let(:stderr) { StringIO.new }
466
+ let(:stdin) { StringIO.new }
467
+
468
+ let(:ui) { Chef::Knife::UI.new(stdout, stderr, stdin, {}) }
469
+
470
+ before do
471
+ knife.ui = ui
472
+ expect(knife).to receive(:exit).with(100)
473
+ end
474
+
475
+ it "formats 401s nicely" do
476
+ response = Net::HTTPUnauthorized.new("1.1", "401", "Unauthorized")
477
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
478
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u no syncronize your clock?"))
479
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("401 Unauthorized", response))
480
+ knife.run_with_pretty_exceptions
481
+ expect(stderr.string).to match(/ERROR: Failed to authenticate to/)
482
+ expect(stderr.string).to match(/Response: y u no syncronize your clock\?/)
483
+ end
484
+
485
+ it "formats 403s nicely" do
486
+ response = Net::HTTPForbidden.new("1.1", "403", "Forbidden")
487
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
488
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u no administrator"))
489
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("403 Forbidden", response))
490
+ allow(knife).to receive(:username).and_return("sadpanda")
491
+ knife.run_with_pretty_exceptions
492
+ expect(stderr.string).to match(/ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action/)
493
+ expect(stderr.string).to match(/Response: y u no administrator/)
494
+ end
495
+
496
+ context "when proxy servers are set" do
497
+ before do
498
+ ENV["http_proxy"] = "xyz"
499
+ end
500
+
501
+ after do
502
+ ENV.delete("http_proxy")
503
+ end
504
+
505
+ it "formats proxy errors nicely" do
506
+ response = Net::HTTPForbidden.new("1.1", "403", "Forbidden")
507
+ response.instance_variable_set(:@read, true)
508
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u no administrator"))
509
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("403 Forbidden", response))
510
+ allow(knife).to receive(:username).and_return("sadpanda")
511
+ knife.run_with_pretty_exceptions
512
+ expect(stderr.string).to match(/ERROR: You authenticated successfully to http.+ as sadpanda but you are not authorized for this action/)
513
+ expect(stderr.string).to match(/ERROR: There are proxy servers configured, your server url may need to be added to NO_PROXY./)
514
+ expect(stderr.string).to match(/Response: y u no administrator/)
515
+ end
516
+ end
517
+
518
+ it "formats 400s nicely" do
519
+ response = Net::HTTPBadRequest.new("1.1", "400", "Bad Request")
520
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
521
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "y u search wrong"))
522
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("400 Bad Request", response))
523
+ knife.run_with_pretty_exceptions
524
+ expect(stderr.string).to match(/ERROR: The data in your request was invalid/)
525
+ expect(stderr.string).to match(/Response: y u search wrong/)
526
+ end
527
+
528
+ it "formats 404s nicely" do
529
+ response = Net::HTTPNotFound.new("1.1", "404", "Not Found")
530
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
531
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "nothing to see here"))
532
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("404 Not Found", response))
533
+ knife.run_with_pretty_exceptions
534
+ expect(stderr.string).to match(/ERROR: The object you are looking for could not be found/)
535
+ expect(stderr.string).to match(/Response: nothing to see here/)
536
+ end
537
+
538
+ it "formats 406s (non-supported API version error) nicely" do
539
+ response = Net::HTTPNotAcceptable.new("1.1", "406", "Not Acceptable")
540
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
541
+
542
+ # set the header
543
+ response["x-ops-server-api-version"] = Chef::JSONCompat.to_json(min_version: "0", max_version: "1", request_version: "10000000")
544
+
545
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "sad trombone"))
546
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("406 Not Acceptable", response))
547
+
548
+ knife.run_with_pretty_exceptions
549
+ expect(stderr.string).to match(/The request that .* sent was using API version 10000000./)
550
+ expect(stderr.string).to match(/The server you sent the request to supports a min API version of 0 and a max API version of 1./)
551
+ expect(stderr.string).to match(/Please either update your .* or the server to be a compatible set./)
552
+ end
553
+
554
+ it "formats 500s nicely" do
555
+ response = Net::HTTPInternalServerError.new("1.1", "500", "Internal Server Error")
556
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
557
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "sad trombone"))
558
+ allow(knife).to receive(:run).and_raise(Net::HTTPFatalError.new("500 Internal Server Error", response))
559
+ knife.run_with_pretty_exceptions
560
+ expect(stderr.string).to match(/ERROR: internal server error/)
561
+ expect(stderr.string).to match(/Response: sad trombone/)
562
+ end
563
+
564
+ it "formats 502s nicely" do
565
+ response = Net::HTTPBadGateway.new("1.1", "502", "Bad Gateway")
566
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
567
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "sadder trombone"))
568
+ allow(knife).to receive(:run).and_raise(Net::HTTPFatalError.new("502 Bad Gateway", response))
569
+ knife.run_with_pretty_exceptions
570
+ expect(stderr.string).to match(/ERROR: bad gateway/)
571
+ expect(stderr.string).to match(/Response: sadder trombone/)
572
+ end
573
+
574
+ it "formats 503s nicely" do
575
+ response = Net::HTTPServiceUnavailable.new("1.1", "503", "Service Unavailable")
576
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
577
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "saddest trombone"))
578
+ allow(knife).to receive(:run).and_raise(Net::HTTPFatalError.new("503 Service Unavailable", response))
579
+ knife.run_with_pretty_exceptions
580
+ expect(stderr.string).to match(/ERROR: Service temporarily unavailable/)
581
+ expect(stderr.string).to match(/Response: saddest trombone/)
582
+ end
583
+
584
+ it "formats other HTTP errors nicely" do
585
+ response = Net::HTTPPaymentRequired.new("1.1", "402", "Payment Required")
586
+ response.instance_variable_set(:@read, true) # I hate you, net/http.
587
+ allow(response).to receive(:body).and_return(Chef::JSONCompat.to_json(error: "nobugfixtillyoubuy"))
588
+ allow(knife).to receive(:run).and_raise(Net::HTTPClientException.new("402 Payment Required", response))
589
+ knife.run_with_pretty_exceptions
590
+ expect(stderr.string).to match(/ERROR: Payment Required/)
591
+ expect(stderr.string).to match(/Response: nobugfixtillyoubuy/)
592
+ end
593
+
594
+ it "formats NameError and NoMethodError nicely" do
595
+ allow(knife).to receive(:run).and_raise(NameError.new("Undefined constant FUUU"))
596
+ knife.run_with_pretty_exceptions
597
+ expect(stderr.string).to match(/ERROR: .* encountered an unexpected error/)
598
+ expect(stderr.string).to match(/This may be a bug in the 'knife' .* command or plugin/)
599
+ expect(stderr.string).to match(/Exception: NameError: Undefined constant FUUU/)
600
+ end
601
+
602
+ it "formats missing private key errors nicely" do
603
+ allow(knife).to receive(:run).and_raise(Chef::Exceptions::PrivateKeyMissing.new("key not there"))
604
+ allow(knife).to receive(:api_key).and_return("/home/root/.chef/no-key-here.pem")
605
+ knife.run_with_pretty_exceptions
606
+ expect(stderr.string).to match(%r{ERROR: Your private key could not be loaded from /home/root/.chef/no-key-here.pem})
607
+ expect(stderr.string).to match(/Check your configuration file and ensure that your private key is readable/)
608
+ end
609
+
610
+ it "formats connection refused errors nicely" do
611
+ allow(knife).to receive(:run).and_raise(Errno::ECONNREFUSED.new("y u no shut up"))
612
+ knife.run_with_pretty_exceptions
613
+ # Errno::ECONNREFUSED message differs by platform
614
+ # *nix = Errno::ECONNREFUSED: Connection refused
615
+ # win32: Errno::ECONNREFUSED: No connection could be made because the target machine actively refused it.
616
+ expect(stderr.string).to match(/ERROR: Network Error: .* - y u no shut up/)
617
+ expect(stderr.string).to match(/Check your .* configuration and network settings/)
618
+ end
619
+
620
+ it "formats SSL errors nicely and suggests to use `knife ssl check` and `knife ssl fetch`" do
621
+ error = OpenSSL::SSL::SSLError.new("SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed")
622
+ allow(knife).to receive(:run).and_raise(error)
623
+
624
+ knife.run_with_pretty_exceptions
625
+
626
+ expected_message = <<~MSG
627
+ ERROR: Could not establish a secure connection to the server.
628
+ Use `.* ssl check` to troubleshoot your SSL configuration.
629
+ If your server uses a self-signed certificate, you can use
630
+ `.* ssl fetch` to make .* trust the server's certificates.
631
+ MSG
632
+ expect(stderr.string).to match(expected_message)
633
+ end
634
+
635
+ end
636
+
637
+ end