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
data/lib/chef/knife.rb CHANGED
@@ -1,677 +1,677 @@
1
- #
2
- # Author:: Adam Jacob (<adam@chef.io>)
3
- # Author:: Christopher Brown (<cb@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
- require "forwardable" unless defined?(Forwardable)
21
- require_relative "knife/version"
22
- require "mixlib/cli" unless defined?(Mixlib::CLI)
23
- require "chef-utils/dsl/default_paths" unless defined?(ChefUtils::DSL::DefaultPaths)
24
- require "chef-utils/dist" unless defined?(ChefUtils::Dist)
25
- require "chef/workstation_config_loader" unless defined?(Chef::WorkstationConfigLoader)
26
- require "chef/mixin/convert_to_class_name" unless defined?(Chef::ConvertToClassName)
27
- require "chef/mixin/default_paths" unless defined?(Chef::Mixin::DefaultPaths)
28
- require_relative "knife/core/subcommand_loader"
29
- require_relative "knife/core/ui"
30
- require "chef/local_mode" unless defined?(Chef::LocalMode)
31
- require "chef/server_api" unless defined?(Chef::ServerAPI)
32
- require "http/authenticator" unless defined?(Chef::HTTP::Authenticator)
33
- require "http/http_request" unless defined?(Chef::HTTP::HTTPRequest)
34
- require "http" unless defined?(Chef::HTTP)
35
- # End
36
-
37
- require "pp" unless defined?(PP)
38
-
39
- require_relative "application/knife"
40
-
41
- class Chef
42
- class Knife
43
-
44
- Chef::HTTP::HTTPRequest.user_agent = "#{ChefUtils::Dist::Infra::PRODUCT} Knife#{Chef::HTTP::HTTPRequest::UA_COMMON}"
45
-
46
- include Mixlib::CLI
47
- include ChefUtils::DSL::DefaultPaths
48
- extend Chef::Mixin::ConvertToClassName
49
- extend Forwardable
50
-
51
- # @note Backwards Compat:
52
- # Ideally, we should not vomit all of these methods into this base class;
53
- # instead, they should be accessed by hitting the ui object directly.
54
- def_delegator :@ui, :stdout
55
- def_delegator :@ui, :stderr
56
- def_delegator :@ui, :stdin
57
- def_delegator :@ui, :msg
58
- def_delegator :@ui, :ask_question
59
- def_delegator :@ui, :pretty_print
60
- def_delegator :@ui, :output
61
- def_delegator :@ui, :format_list_for_display
62
- def_delegator :@ui, :format_for_display
63
- def_delegator :@ui, :format_cookbook_list_for_display
64
- def_delegator :@ui, :edit_data
65
- def_delegator :@ui, :edit_hash
66
- def_delegator :@ui, :edit_object
67
- def_delegator :@ui, :confirm
68
-
69
- attr_accessor :name_args
70
- attr_accessor :ui
71
-
72
- # knife acl subcommands are grouped in this category using this constant to verify.
73
- OPSCODE_HOSTED_CHEF_ACCESS_CONTROL = %w{acl group user}.freeze
74
-
75
- # knife opc subcommands are grouped in this category using this constant to verify.
76
- CHEF_ORGANIZATION_MANAGEMENT = %w{opc}.freeze
77
-
78
- # Configure mixlib-cli to always separate defaults from user-supplied CLI options
79
- def self.use_separate_defaults?
80
- true
81
- end
82
-
83
- def self.ui
84
- @ui ||= Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
85
- end
86
-
87
- def self.msg(msg = "")
88
- ui.msg(msg)
89
- end
90
-
91
- def self.reset_config_loader!
92
- @@chef_config_dir = nil
93
- @config_loader = nil
94
- end
95
-
96
- def self.reset_subcommands!
97
- @@subcommands = {}
98
- @subcommands_by_category = nil
99
- end
100
-
101
- def self.inherited(subclass)
102
- super
103
- unless subclass.unnamed?
104
- subcommands[subclass.snake_case_name] = subclass
105
- subcommand_files[subclass.snake_case_name] +=
106
- if subclass.superclass.to_s == "Chef::ChefFS::Knife"
107
- # ChefFS-based commands have a superclass that defines an
108
- # inherited method which calls super. This means that the
109
- # top of the call stack is not the class definition for
110
- # our subcommand. Try the second entry in the call stack.
111
- [path_from_caller(caller[1])]
112
- else
113
- [path_from_caller(caller[0])]
114
- end
115
- end
116
- end
117
-
118
- # Explicitly set the category for the current command to +new_category+
119
- # The category is normally determined from the first word of the command
120
- # name, but some commands make more sense using two or more words
121
- # @param new_category [String] value to set the category to (see examples)
122
- #
123
- # @example Data bag commands would be in the 'data' category by default. To
124
- # put them in the 'data bag' category:
125
- # category('data bag')
126
- def self.category(new_category)
127
- @category = new_category
128
- end
129
-
130
- def self.subcommand_category
131
- @category || snake_case_name.split("_").first unless unnamed?
132
- end
133
-
134
- def self.snake_case_name
135
- convert_to_snake_case(name.split("::").last) unless unnamed?
136
- end
137
-
138
- def self.common_name
139
- snake_case_name.split("_").join(" ")
140
- end
141
-
142
- # Does this class have a name? (Classes created via Class.new don't)
143
- def self.unnamed?
144
- name.nil? || name.empty?
145
- end
146
-
147
- def self.subcommand_loader
148
- @subcommand_loader ||= Chef::Knife::SubcommandLoader.for_config(chef_config_dir)
149
- end
150
-
151
- def self.load_commands
152
- @commands_loaded ||= subcommand_loader.load_commands
153
- end
154
-
155
- def self.guess_category(args)
156
- subcommand_loader.guess_category(args)
157
- end
158
-
159
- def self.subcommand_class_from(args)
160
- if args.size == 1 && args[0].strip.casecmp("rehash") == 0
161
- # To prevent issues with the rehash file not pointing to the correct plugins,
162
- # we always use the glob loader when regenerating the rehash file
163
- @subcommand_loader = Chef::Knife::SubcommandLoader.gem_glob_loader(chef_config_dir)
164
- end
165
- subcommand_loader.command_class_from(args) || subcommand_not_found!(args)
166
- end
167
-
168
- def self.subcommands
169
- @@subcommands ||= {}
170
- end
171
-
172
- def self.subcommand_files
173
- @@subcommand_files ||= Hash.new([])
174
- end
175
-
176
- def self.subcommands_by_category
177
- unless @subcommands_by_category
178
- @subcommands_by_category = Hash.new { |hash, key| hash[key] = [] }
179
- subcommands.each do |snake_cased, klass|
180
- @subcommands_by_category[klass.subcommand_category] << snake_cased
181
- end
182
- end
183
- @subcommands_by_category
184
- end
185
-
186
- # Shared with subclasses
187
- @@chef_config_dir = nil
188
-
189
- def self.config_loader
190
- @config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log)
191
- end
192
-
193
- def self.load_config(explicit_config_file, profile)
194
- config_loader.explicit_config_file = explicit_config_file
195
- config_loader.profile = profile
196
- config_loader.load
197
-
198
- ui.warn("No knife configuration file found. See https://docs.chef.io/config_rb/ for details.") if config_loader.no_config_found?
199
-
200
- config_loader
201
- rescue Exceptions::ConfigurationError => e
202
- ui.error(ui.color("CONFIGURATION ERROR:", :red) + e.message)
203
- exit 1
204
- end
205
-
206
- def self.chef_config_dir
207
- @@chef_config_dir ||= config_loader.chef_config_dir
208
- end
209
-
210
- # Run knife for the given +args+ (ARGV), adding +options+ to the list of
211
- # CLI options that the subcommand knows how to handle.
212
- #
213
- # @param args [Array] The arguments. Usually ARGV
214
- # @param options [Mixlib::CLI option parser hash] These +options+ are how
215
- # subcommands know about global knife CLI options
216
- #
217
- def self.run(args, options = {})
218
- # Fallback debug logging. Normally the logger isn't configured until we
219
- # read the config, but this means any logging that happens before the
220
- # config file is read may be lost. If the KNIFE_DEBUG variable is set, we
221
- # setup the logger for debug logging to stderr immediately to catch info
222
- # from early in the setup process.
223
- if ENV["KNIFE_DEBUG"]
224
- Chef::Log.init($stderr)
225
- Chef::Log.level(:debug)
226
- end
227
-
228
- subcommand_class = subcommand_class_from(args)
229
- subcommand_class.options = options.merge!(subcommand_class.options)
230
- subcommand_class.load_deps
231
- instance = subcommand_class.new(args)
232
- instance.configure_chef
233
- instance.run_with_pretty_exceptions
234
- end
235
-
236
- def self.dependency_loaders
237
- @dependency_loaders ||= []
238
- end
239
-
240
- def self.deps(&block)
241
- dependency_loaders << block
242
- end
243
-
244
- def self.load_deps
245
- dependency_loaders.each(&:call)
246
- end
247
-
248
- OFFICIAL_PLUGINS = %w{lpar openstack push rackspace vcenter}.freeze
249
-
250
- class << self
251
- def list_commands(preferred_category = nil)
252
- category_desc = preferred_category ? preferred_category + " " : ""
253
- msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n"
254
- subcommand_loader.list_commands(preferred_category).sort.each do |category, commands|
255
- next if /deprecated/i.match?(category)
256
-
257
- msg "** #{category.upcase} COMMANDS **"
258
- commands.sort.each do |command|
259
- subcommand_loader.load_command(command)
260
- msg subcommands[command].banner if subcommands[command]
261
- end
262
- msg
263
- end
264
- end
265
-
266
- private
267
-
268
- # @api private
269
- def path_from_caller(caller_line)
270
- caller_line.split(/:\d+/).first
271
- end
272
-
273
- # Error out and print usage. probably because the arguments given by the
274
- # user could not be resolved to a subcommand.
275
- # @api private
276
- def subcommand_not_found!(args)
277
- ui.fatal("Cannot find subcommand for: '#{args.join(" ")}'")
278
-
279
- # Mention rehash when the subcommands cache(plugin_manifest.json) is used
280
- if subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::HashedCommandLoader)
281
- ui.info("If this is a recently installed plugin, please run 'knife rehash' to update the subcommands cache.")
282
- end
283
-
284
- if CHEF_ORGANIZATION_MANAGEMENT.include?(args[0])
285
- list_commands("CHEF ORGANIZATION MANAGEMENT")
286
- elsif category_commands = guess_category(args)
287
- list_commands(category_commands)
288
- elsif OFFICIAL_PLUGINS.include?(args[0]) # command was an uninstalled official chef knife plugin
289
- ui.info("Use `#{ChefUtils::Dist::Infra::EXEC} gem install knife-#{args[0]}` to install the plugin into Chef Workstation")
290
- else
291
- list_commands
292
- end
293
-
294
- exit 10
295
- end
296
-
297
- # @api private
298
- def reset_config_path!
299
- @@chef_config_dir = nil
300
- end
301
-
302
- end
303
-
304
- reset_config_path!
305
-
306
- # Create a new instance of the current class configured for the given
307
- # arguments and options
308
- def initialize(argv = [])
309
- super() # having to call super in initialize is the most annoying anti-pattern :(
310
- @ui = Chef::Knife::UI.new(STDOUT, STDERR, STDIN, config)
311
-
312
- command_name_words = self.class.snake_case_name.split("_")
313
-
314
- # Mixlib::CLI ignores the embedded name_args
315
- @name_args = parse_options(argv)
316
- @name_args.delete(command_name_words.join("-"))
317
- @name_args.reject! { |name_arg| command_name_words.delete(name_arg) }
318
-
319
- # knife node run_list add requires that we have extra logic to handle
320
- # the case that command name words could be joined by an underscore :/
321
- command_name_joined = command_name_words.join("_")
322
- @name_args.reject! { |name_arg| command_name_joined == name_arg }
323
-
324
- # Similar handling for hyphens.
325
- command_name_joined = command_name_words.join("-")
326
- @name_args.reject! { |name_arg| command_name_joined == name_arg }
327
-
328
- if config[:help]
329
- msg opt_parser
330
- exit 1
331
- end
332
-
333
- # Grab a copy before config merge occurs, so that we can later identify
334
- # where a given config value is sourced from.
335
- @original_config = config.dup
336
-
337
- # copy Mixlib::CLI over so that it can be configured in config.rb/knife.rb
338
- # config file
339
- Chef::Config[:verbosity] = config[:verbosity] if config[:verbosity]
340
- end
341
-
342
- def parse_options(args)
343
- super
344
- rescue OptionParser::InvalidOption => e
345
- puts "Error: " + e.to_s
346
- show_usage
347
- exit(1)
348
- end
349
-
350
- # This is all set and default mixlib-config values. We only need the default
351
- # values here (the set values are explicitly mixed in again later), but there is
352
- # no mixlib-config API to get a Hash back with only the default values.
353
- #
354
- # Assumption: since config_file_defaults is the lowest precedence it doesn't matter
355
- # that we include the set values here, but this is a hack and makes the name of the
356
- # method a lie. FIXME: make the name not a lie by adding an API to mixlib-config.
357
- #
358
- # @api private
359
- #
360
- def config_file_defaults
361
- Chef::Config[:knife].save(true) # this is like "dup" to a (real) Hash, and includes default values (and user set values)
362
- end
363
-
364
- # This is only the user-set mixlib-config values. We do not include the defaults
365
- # here so that the config defaults do not override the cli defaults.
366
- #
367
- # @api private
368
- #
369
- def config_file_settings
370
- Chef::Config[:knife].save(false) # this is like "dup" to a (real) Hash, and does not include default values (just user set values)
371
- end
372
-
373
- # config is merged in this order (inverse of precedence)
374
- # config_file_defaults - Chef::Config[:knife] defaults from chef-config (XXX: this also includes the settings, but they get overwritten)
375
- # default_config - mixlib-cli defaults (accessor from mixlib-cli)
376
- # config_file_settings - Chef::Config[:knife] user settings from the client.rb file
377
- # config - mixlib-cli settings (accessor from mixlib-cli)
378
- #
379
- def merge_configs
380
- # Update our original_config - if someone has created a knife command
381
- # instance directly, they are likely ot have set cmd.config values directly
382
- # as well, at which point our saved original config is no longer up to date.
383
- @original_config = config.dup
384
- # other code may have a handle to the config object, so use Hash#replace to deliberately
385
- # update-in-place.
386
- config.replace(config_file_defaults.merge(default_config).merge(config_file_settings).merge(config))
387
- end
388
-
389
- #
390
- # Determine the source of a given configuration key
391
- #
392
- # @argument key [Symbol] a configuration key
393
- # @return [Symbol,NilClass] return the source of the config key,
394
- # one of:
395
- # - :cli - this was explicitly provided on the CLI
396
- # - :config - this came from Chef::Config[:knife] explicitly being set
397
- # - :cli_default - came from a declared CLI `option`'s `default` value.
398
- # - :config_default - this came from Chef::Config[:knife]'s defaults
399
- # - nil - if the key could not be found in any source.
400
- # This can happen when it is invalid, or has been
401
- # set directly into #config without then calling #merge_config
402
- def config_source(key)
403
- return :cli if @original_config.include? key
404
- return :config if config_file_settings.key? key
405
- return :cli_default if default_config.include? key
406
- return :config_default if config_file_defaults.key? key # must come after :config check
407
-
408
- nil
409
- end
410
-
411
- # Catch-all method that does any massaging needed for various config
412
- # components, such as expanding file paths and converting verbosity level
413
- # into log level.
414
- def apply_computed_config
415
- Chef::Config[:color] = config[:color]
416
-
417
- # If the verbosity is not set, use what is already present on the log_level config.
418
- Chef::Config[:log_level] = case Chef::Config[:verbosity]
419
- when 0
420
- :warn
421
- when 1
422
- :info
423
- when 2
424
- :debug
425
- when nil
426
- # The default log_level is auto and that is not a valid log_level.
427
- Chef::Config[:log_level] == :auto ? :warn : Chef::Config[:log_level]
428
- else
429
- :trace
430
- end
431
-
432
- Chef::Config[:log_level] = :trace if ENV["KNIFE_DEBUG"]
433
-
434
- Chef::Config[:node_name] = config[:node_name] if config[:node_name]
435
- Chef::Config[:client_key] = config[:client_key] if config[:client_key]
436
- Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
437
- Chef::Config[:environment] = config[:environment] if config[:environment]
438
-
439
- Chef::Config.local_mode = config[:local_mode] if config.key?(:local_mode)
440
-
441
- Chef::Config.listen = config[:listen] if config.key?(:listen)
442
-
443
- if Chef::Config.local_mode && !Chef::Config.key?(:cookbook_path) && !Chef::Config.key?(:chef_repo_path)
444
- Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
445
- end
446
- Chef::Config.chef_zero.host = config[:chef_zero_host] if config[:chef_zero_host]
447
- Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port]
448
-
449
- # Expand a relative path from the config directory. Config from command
450
- # line should already be expanded, and absolute paths will be unchanged.
451
- if Chef::Config[:client_key] && config[:config_file]
452
- Chef::Config[:client_key] = File.expand_path(Chef::Config[:client_key], File.dirname(config[:config_file]))
453
- end
454
-
455
- Mixlib::Log::Formatter.show_time = false
456
- Chef::Log.init(Chef::Config[:log_location])
457
- Chef::Log.level(Chef::Config[:log_level] || :error)
458
- end
459
-
460
- def configure_chef
461
- # knife needs to send logger output to STDERR by default
462
- Chef::Config[:log_location] = STDERR
463
- config_loader = self.class.load_config(config[:config_file], config[:profile])
464
- config[:config_file] = config_loader.config_location
465
-
466
- # For CLI options like `--config-option key=value`. These have to get
467
- # parsed and applied separately.
468
- extra_config_options = config.delete(:config_option)
469
-
470
- merge_configs
471
- apply_computed_config
472
-
473
- # This has to be after apply_computed_config so that Mixlib::Log is configured
474
- Chef::Log.info("Using configuration from #{config[:config_file]}") if config[:config_file]
475
-
476
- begin
477
- Chef::Config.apply_extra_config_options(extra_config_options)
478
- rescue ChefConfig::UnparsableConfigOption => e
479
- ui.error e.message
480
- show_usage
481
- exit(1)
482
- end
483
-
484
- Chef::Config.export_proxies
485
- end
486
-
487
- def show_usage
488
- stdout.puts("USAGE: " + opt_parser.to_s)
489
- end
490
-
491
- def run_with_pretty_exceptions(raise_exception = false)
492
- unless respond_to?(:run)
493
- ui.error "You need to add a #run method to your knife command before you can use it"
494
- end
495
- ENV["PATH"] = default_paths if Chef::Config[:enforce_default_paths] || Chef::Config[:enforce_path_sanity]
496
- maybe_setup_fips
497
- Chef::LocalMode.with_server_connectivity do
498
- run
499
- end
500
- rescue Exception => e
501
- raise if raise_exception || ( Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 2 )
502
-
503
- humanize_exception(e)
504
- exit 100
505
- end
506
-
507
- def humanize_exception(e)
508
- case e
509
- when SystemExit
510
- raise # make sure exit passes through.
511
- when Net::HTTPClientException, Net::HTTPFatalError
512
- humanize_http_exception(e)
513
- when OpenSSL::SSL::SSLError
514
- ui.error "Could not establish a secure connection to the server."
515
- ui.info "Use `knife ssl check` to troubleshoot your SSL configuration."
516
- ui.info "If your server uses a self-signed certificate, you can use"
517
- ui.info "`knife ssl fetch` to make knife trust the server's certificates."
518
- ui.info ""
519
- ui.info "Original Exception: #{e.class.name}: #{e.message}"
520
- when Errno::ECONNREFUSED, Timeout::Error, Errno::ETIMEDOUT, SocketError
521
- ui.error "Network Error: #{e.message}"
522
- ui.info "Check your knife configuration and network settings"
523
- when NameError, NoMethodError
524
- ui.error "knife encountered an unexpected error"
525
- ui.info "This may be a bug in the '#{self.class.common_name}' knife command or plugin"
526
- ui.info "Please collect the output of this command with the `-VVV` option before filing a bug report."
527
- ui.info "Exception: #{e.class.name}: #{e.message}"
528
- when Chef::Exceptions::PrivateKeyMissing
529
- ui.error "Your private key could not be loaded from #{api_key}"
530
- ui.info "Check your configuration file and ensure that your private key is readable"
531
- when Chef::Exceptions::InvalidRedirect
532
- ui.error "Invalid Redirect: #{e.message}"
533
- ui.info "Change your server location in config.rb/knife.rb to the server's FQDN to avoid unwanted redirections."
534
- else
535
- ui.error "#{e.class.name}: #{e.message}"
536
- end
537
- end
538
-
539
- def humanize_http_exception(e)
540
- response = e.response
541
- case response
542
- when Net::HTTPUnauthorized
543
- ui.error "Failed to authenticate to #{server_url} as #{username} with key #{api_key}"
544
- ui.info "Response: #{format_rest_error(response)}"
545
- when Net::HTTPForbidden
546
- ui.error "You authenticated successfully to #{server_url} as #{username} but you are not authorized for this action."
547
- proxy_env_vars = ENV.to_hash.keys.map(&:downcase) & %w{http_proxy https_proxy ftp_proxy socks_proxy no_proxy}
548
- unless proxy_env_vars.empty?
549
- ui.error "There are proxy servers configured, your server url may need to be added to NO_PROXY."
550
- end
551
- ui.info "Response: #{format_rest_error(response)}"
552
- when Net::HTTPBadRequest
553
- ui.error "The data in your request was invalid"
554
- ui.info "Response: #{format_rest_error(response)}"
555
- when Net::HTTPNotFound
556
- ui.error "The object you are looking for could not be found"
557
- ui.info "Response: #{format_rest_error(response)}"
558
- when Net::HTTPInternalServerError
559
- ui.error "internal server error"
560
- ui.info "Response: #{format_rest_error(response)}"
561
- when Net::HTTPBadGateway
562
- ui.error "bad gateway"
563
- ui.info "Response: #{format_rest_error(response)}"
564
- when Net::HTTPServiceUnavailable
565
- ui.error "Service temporarily unavailable"
566
- ui.info "Response: #{format_rest_error(response)}"
567
- when Net::HTTPNotAcceptable
568
- version_header = Chef::JSONCompat.from_json(response["x-ops-server-api-version"])
569
- client_api_version = version_header["request_version"]
570
- min_server_version = version_header["min_version"]
571
- max_server_version = version_header["max_version"]
572
- ui.error "The API version that Knife is using is not supported by the server you sent this request to."
573
- ui.info "The request that Knife sent was using API version #{client_api_version}."
574
- ui.info "The server you sent the request to supports a min API version of #{min_server_version} and a max API version of #{max_server_version}."
575
- ui.info "Please either update your #{ChefUtils::Dist::Infra::PRODUCT} or the server to be a compatible set."
576
- else
577
- ui.error response.message
578
- ui.info "Response: #{format_rest_error(response)}"
579
- end
580
- end
581
-
582
- def username
583
- Chef::Config[:node_name]
584
- end
585
-
586
- def api_key
587
- Chef::Config[:client_key]
588
- end
589
-
590
- # Parses JSON from the error response sent by Chef Server and returns the
591
- # error message
592
- #--
593
- # TODO: this code belongs in Chef::REST
594
- def format_rest_error(response)
595
- Array(Chef::JSONCompat.from_json(response.body)["error"]).join("; ")
596
- rescue Exception
597
- response.body
598
- end
599
-
600
- # FIXME: yard with @yield
601
- def create_object(object, pretty_name = nil, object_class: nil)
602
- output = if object_class
603
- edit_data(object, object_class: object_class)
604
- else
605
- edit_hash(object)
606
- end
607
-
608
- if Kernel.block_given?
609
- output = yield(output)
610
- else
611
- output.save
612
- end
613
-
614
- pretty_name ||= output
615
-
616
- msg("Created #{pretty_name}")
617
-
618
- output(output) if config[:print_after]
619
- end
620
-
621
- # FIXME: yard with @yield
622
- def delete_object(klass, name, delete_name = nil)
623
- confirm("Do you really want to delete #{name}")
624
-
625
- if Kernel.block_given?
626
- object = yield
627
- else
628
- object = klass.load(name)
629
- object.destroy
630
- end
631
-
632
- output(format_for_display(object)) if config[:print_after]
633
-
634
- obj_name = delete_name ? "#{delete_name}[#{name}]" : object
635
- msg("Deleted #{obj_name}")
636
- end
637
-
638
- # helper method for testing if a field exists
639
- # and returning the usage and proper error if not
640
- def test_mandatory_field(field, fieldname)
641
- if field.nil?
642
- show_usage
643
- ui.fatal("You must specify a #{fieldname}")
644
- exit 1
645
- end
646
- end
647
-
648
- def rest
649
- @rest ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url])
650
- end
651
-
652
- def noauth_rest
653
- @rest ||= begin
654
- require "chef/http/simple_json" unless defined?(Chef::HTTP::SimpleJSON)
655
- Chef::HTTP::SimpleJSON.new(Chef::Config[:chef_server_url])
656
- end
657
- end
658
-
659
- def server_url
660
- Chef::Config[:chef_server_url]
661
- end
662
-
663
- def maybe_setup_fips
664
- unless config[:fips].nil?
665
- Chef::Config[:fips] = config[:fips]
666
- end
667
- Chef::Config.init_openssl
668
- end
669
-
670
- def root_rest
671
- @root_rest ||= begin
672
- require "chef/server_api" unless defined? Chef::ServerAPI
673
- Chef::ServerAPI.new(Chef::Config[:chef_server_root])
674
- end
675
- end
676
- end
677
- end
1
+ #
2
+ # Author:: Adam Jacob (<adam@chef.io>)
3
+ # Author:: Christopher Brown (<cb@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
+ require "forwardable" unless defined?(Forwardable)
21
+ require_relative "knife/version"
22
+ require "mixlib/cli" unless defined?(Mixlib::CLI)
23
+ require "chef-utils/dsl/default_paths" unless defined?(ChefUtils::DSL::DefaultPaths)
24
+ require "chef-utils/dist" unless defined?(ChefUtils::Dist)
25
+ require "chef/workstation_config_loader" unless defined?(Chef::WorkstationConfigLoader)
26
+ require "chef/mixin/convert_to_class_name" unless defined?(Chef::ConvertToClassName)
27
+ require "chef/mixin/default_paths" unless defined?(Chef::Mixin::DefaultPaths)
28
+ require_relative "knife/core/subcommand_loader"
29
+ require_relative "knife/core/ui"
30
+ require "chef/local_mode" unless defined?(Chef::LocalMode)
31
+ require "chef/server_api" unless defined?(Chef::ServerAPI)
32
+ require "http/authenticator" unless defined?(Chef::HTTP::Authenticator)
33
+ require "http/http_request" unless defined?(Chef::HTTP::HTTPRequest)
34
+ require "http" unless defined?(Chef::HTTP)
35
+ # End
36
+
37
+ require "pp" unless defined?(PP)
38
+
39
+ require_relative "application/knife"
40
+
41
+ class Chef
42
+ class Knife
43
+
44
+ Chef::HTTP::HTTPRequest.user_agent = "#{ChefUtils::Dist::Infra::PRODUCT} Knife#{Chef::HTTP::HTTPRequest::UA_COMMON}"
45
+
46
+ include Mixlib::CLI
47
+ include ChefUtils::DSL::DefaultPaths
48
+ extend Chef::Mixin::ConvertToClassName
49
+ extend Forwardable
50
+
51
+ # @note Backwards Compat:
52
+ # Ideally, we should not vomit all of these methods into this base class;
53
+ # instead, they should be accessed by hitting the ui object directly.
54
+ def_delegator :@ui, :stdout
55
+ def_delegator :@ui, :stderr
56
+ def_delegator :@ui, :stdin
57
+ def_delegator :@ui, :msg
58
+ def_delegator :@ui, :ask_question
59
+ def_delegator :@ui, :pretty_print
60
+ def_delegator :@ui, :output
61
+ def_delegator :@ui, :format_list_for_display
62
+ def_delegator :@ui, :format_for_display
63
+ def_delegator :@ui, :format_cookbook_list_for_display
64
+ def_delegator :@ui, :edit_data
65
+ def_delegator :@ui, :edit_hash
66
+ def_delegator :@ui, :edit_object
67
+ def_delegator :@ui, :confirm
68
+
69
+ attr_accessor :name_args
70
+ attr_accessor :ui
71
+
72
+ # knife acl subcommands are grouped in this category using this constant to verify.
73
+ OPSCODE_HOSTED_CHEF_ACCESS_CONTROL = %w{acl group user}.freeze
74
+
75
+ # knife opc subcommands are grouped in this category using this constant to verify.
76
+ CHEF_ORGANIZATION_MANAGEMENT = %w{opc}.freeze
77
+
78
+ # Configure mixlib-cli to always separate defaults from user-supplied CLI options
79
+ def self.use_separate_defaults?
80
+ true
81
+ end
82
+
83
+ def self.ui
84
+ @ui ||= Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
85
+ end
86
+
87
+ def self.msg(msg = "")
88
+ ui.msg(msg)
89
+ end
90
+
91
+ def self.reset_config_loader!
92
+ @@chef_config_dir = nil
93
+ @config_loader = nil
94
+ end
95
+
96
+ def self.reset_subcommands!
97
+ @@subcommands = {}
98
+ @subcommands_by_category = nil
99
+ end
100
+
101
+ def self.inherited(subclass)
102
+ super
103
+ unless subclass.unnamed?
104
+ subcommands[subclass.snake_case_name] = subclass
105
+ subcommand_files[subclass.snake_case_name] +=
106
+ if subclass.superclass.to_s == "Chef::ChefFS::Knife"
107
+ # ChefFS-based commands have a superclass that defines an
108
+ # inherited method which calls super. This means that the
109
+ # top of the call stack is not the class definition for
110
+ # our subcommand. Try the second entry in the call stack.
111
+ [path_from_caller(caller[1])]
112
+ else
113
+ [path_from_caller(caller[0])]
114
+ end
115
+ end
116
+ end
117
+
118
+ # Explicitly set the category for the current command to +new_category+
119
+ # The category is normally determined from the first word of the command
120
+ # name, but some commands make more sense using two or more words
121
+ # @param new_category [String] value to set the category to (see examples)
122
+ #
123
+ # @example Data bag commands would be in the 'data' category by default. To
124
+ # put them in the 'data bag' category:
125
+ # category('data bag')
126
+ def self.category(new_category)
127
+ @category = new_category
128
+ end
129
+
130
+ def self.subcommand_category
131
+ @category || snake_case_name.split("_").first unless unnamed?
132
+ end
133
+
134
+ def self.snake_case_name
135
+ convert_to_snake_case(name.split("::").last) unless unnamed?
136
+ end
137
+
138
+ def self.common_name
139
+ snake_case_name.split("_").join(" ")
140
+ end
141
+
142
+ # Does this class have a name? (Classes created via Class.new don't)
143
+ def self.unnamed?
144
+ name.nil? || name.empty?
145
+ end
146
+
147
+ def self.subcommand_loader
148
+ @subcommand_loader ||= Chef::Knife::SubcommandLoader.for_config(chef_config_dir)
149
+ end
150
+
151
+ def self.load_commands
152
+ @commands_loaded ||= subcommand_loader.load_commands
153
+ end
154
+
155
+ def self.guess_category(args)
156
+ subcommand_loader.guess_category(args)
157
+ end
158
+
159
+ def self.subcommand_class_from(args)
160
+ if args.size == 1 && args[0].strip.casecmp("rehash") == 0
161
+ # To prevent issues with the rehash file not pointing to the correct plugins,
162
+ # we always use the glob loader when regenerating the rehash file
163
+ @subcommand_loader = Chef::Knife::SubcommandLoader.gem_glob_loader(chef_config_dir)
164
+ end
165
+ subcommand_loader.command_class_from(args) || subcommand_not_found!(args)
166
+ end
167
+
168
+ def self.subcommands
169
+ @@subcommands ||= {}
170
+ end
171
+
172
+ def self.subcommand_files
173
+ @@subcommand_files ||= Hash.new([])
174
+ end
175
+
176
+ def self.subcommands_by_category
177
+ unless @subcommands_by_category
178
+ @subcommands_by_category = Hash.new { |hash, key| hash[key] = [] }
179
+ subcommands.each do |snake_cased, klass|
180
+ @subcommands_by_category[klass.subcommand_category] << snake_cased
181
+ end
182
+ end
183
+ @subcommands_by_category
184
+ end
185
+
186
+ # Shared with subclasses
187
+ @@chef_config_dir = nil
188
+
189
+ def self.config_loader
190
+ @config_loader ||= WorkstationConfigLoader.new(nil, Chef::Log)
191
+ end
192
+
193
+ def self.load_config(explicit_config_file, profile)
194
+ config_loader.explicit_config_file = explicit_config_file
195
+ config_loader.profile = profile
196
+ config_loader.load
197
+
198
+ ui.warn("No knife configuration file found. See https://docs.chef.io/config_rb/ for details.") if config_loader.no_config_found?
199
+
200
+ config_loader
201
+ rescue Exceptions::ConfigurationError => e
202
+ ui.error(ui.color("CONFIGURATION ERROR:", :red) + e.message)
203
+ exit 1
204
+ end
205
+
206
+ def self.chef_config_dir
207
+ @@chef_config_dir ||= config_loader.chef_config_dir
208
+ end
209
+
210
+ # Run knife for the given +args+ (ARGV), adding +options+ to the list of
211
+ # CLI options that the subcommand knows how to handle.
212
+ #
213
+ # @param args [Array] The arguments. Usually ARGV
214
+ # @param options [Mixlib::CLI option parser hash] These +options+ are how
215
+ # subcommands know about global knife CLI options
216
+ #
217
+ def self.run(args, options = {})
218
+ # Fallback debug logging. Normally the logger isn't configured until we
219
+ # read the config, but this means any logging that happens before the
220
+ # config file is read may be lost. If the KNIFE_DEBUG variable is set, we
221
+ # setup the logger for debug logging to stderr immediately to catch info
222
+ # from early in the setup process.
223
+ if ENV["KNIFE_DEBUG"]
224
+ Chef::Log.init($stderr)
225
+ Chef::Log.level(:debug)
226
+ end
227
+
228
+ subcommand_class = subcommand_class_from(args)
229
+ subcommand_class.options = options.merge!(subcommand_class.options)
230
+ subcommand_class.load_deps
231
+ instance = subcommand_class.new(args)
232
+ instance.configure_chef
233
+ instance.run_with_pretty_exceptions
234
+ end
235
+
236
+ def self.dependency_loaders
237
+ @dependency_loaders ||= []
238
+ end
239
+
240
+ def self.deps(&block)
241
+ dependency_loaders << block
242
+ end
243
+
244
+ def self.load_deps
245
+ dependency_loaders.each(&:call)
246
+ end
247
+
248
+ OFFICIAL_PLUGINS = %w{lpar openstack push rackspace vcenter}.freeze
249
+
250
+ class << self
251
+ def list_commands(preferred_category = nil)
252
+ category_desc = preferred_category ? preferred_category + " " : ""
253
+ msg "Available #{category_desc}subcommands: (for details, knife SUB-COMMAND --help)\n\n"
254
+ subcommand_loader.list_commands(preferred_category).sort.each do |category, commands|
255
+ next if /deprecated/i.match?(category)
256
+
257
+ msg "** #{category.upcase} COMMANDS **"
258
+ commands.sort.each do |command|
259
+ subcommand_loader.load_command(command)
260
+ msg subcommands[command].banner if subcommands[command]
261
+ end
262
+ msg
263
+ end
264
+ end
265
+
266
+ private
267
+
268
+ # @api private
269
+ def path_from_caller(caller_line)
270
+ caller_line.split(/:\d+/).first
271
+ end
272
+
273
+ # Error out and print usage. probably because the arguments given by the
274
+ # user could not be resolved to a subcommand.
275
+ # @api private
276
+ def subcommand_not_found!(args)
277
+ ui.fatal("Cannot find subcommand for: '#{args.join(" ")}'")
278
+
279
+ # Mention rehash when the subcommands cache(plugin_manifest.json) is used
280
+ if subcommand_loader.is_a?(Chef::Knife::SubcommandLoader::HashedCommandLoader)
281
+ ui.info("If this is a recently installed plugin, please run 'knife rehash' to update the subcommands cache.")
282
+ end
283
+
284
+ if CHEF_ORGANIZATION_MANAGEMENT.include?(args[0])
285
+ list_commands("CHEF ORGANIZATION MANAGEMENT")
286
+ elsif category_commands = guess_category(args)
287
+ list_commands(category_commands)
288
+ elsif OFFICIAL_PLUGINS.include?(args[0]) # command was an uninstalled official chef knife plugin
289
+ ui.info("Use `#{ChefUtils::Dist::Infra::EXEC} gem install knife-#{args[0]}` to install the plugin into Chef Workstation")
290
+ else
291
+ list_commands
292
+ end
293
+
294
+ exit 10
295
+ end
296
+
297
+ # @api private
298
+ def reset_config_path!
299
+ @@chef_config_dir = nil
300
+ end
301
+
302
+ end
303
+
304
+ reset_config_path!
305
+
306
+ # Create a new instance of the current class configured for the given
307
+ # arguments and options
308
+ def initialize(argv = [])
309
+ super() # having to call super in initialize is the most annoying anti-pattern :(
310
+ @ui = Chef::Knife::UI.new(STDOUT, STDERR, STDIN, config)
311
+
312
+ command_name_words = self.class.snake_case_name.split("_")
313
+
314
+ # Mixlib::CLI ignores the embedded name_args
315
+ @name_args = parse_options(argv)
316
+ @name_args.delete(command_name_words.join("-"))
317
+ @name_args.reject! { |name_arg| command_name_words.delete(name_arg) }
318
+
319
+ # knife node run_list add requires that we have extra logic to handle
320
+ # the case that command name words could be joined by an underscore :/
321
+ command_name_joined = command_name_words.join("_")
322
+ @name_args.reject! { |name_arg| command_name_joined == name_arg }
323
+
324
+ # Similar handling for hyphens.
325
+ command_name_joined = command_name_words.join("-")
326
+ @name_args.reject! { |name_arg| command_name_joined == name_arg }
327
+
328
+ if config[:help]
329
+ msg opt_parser
330
+ exit 1
331
+ end
332
+
333
+ # Grab a copy before config merge occurs, so that we can later identify
334
+ # where a given config value is sourced from.
335
+ @original_config = config.dup
336
+
337
+ # copy Mixlib::CLI over so that it can be configured in config.rb/knife.rb
338
+ # config file
339
+ Chef::Config[:verbosity] = config[:verbosity] if config[:verbosity]
340
+ end
341
+
342
+ def parse_options(args)
343
+ super
344
+ rescue OptionParser::InvalidOption => e
345
+ puts "Error: " + e.to_s
346
+ show_usage
347
+ exit(1)
348
+ end
349
+
350
+ # This is all set and default mixlib-config values. We only need the default
351
+ # values here (the set values are explicitly mixed in again later), but there is
352
+ # no mixlib-config API to get a Hash back with only the default values.
353
+ #
354
+ # Assumption: since config_file_defaults is the lowest precedence it doesn't matter
355
+ # that we include the set values here, but this is a hack and makes the name of the
356
+ # method a lie. FIXME: make the name not a lie by adding an API to mixlib-config.
357
+ #
358
+ # @api private
359
+ #
360
+ def config_file_defaults
361
+ Chef::Config[:knife].save(true) # this is like "dup" to a (real) Hash, and includes default values (and user set values)
362
+ end
363
+
364
+ # This is only the user-set mixlib-config values. We do not include the defaults
365
+ # here so that the config defaults do not override the cli defaults.
366
+ #
367
+ # @api private
368
+ #
369
+ def config_file_settings
370
+ Chef::Config[:knife].save(false) # this is like "dup" to a (real) Hash, and does not include default values (just user set values)
371
+ end
372
+
373
+ # config is merged in this order (inverse of precedence)
374
+ # config_file_defaults - Chef::Config[:knife] defaults from chef-config (XXX: this also includes the settings, but they get overwritten)
375
+ # default_config - mixlib-cli defaults (accessor from mixlib-cli)
376
+ # config_file_settings - Chef::Config[:knife] user settings from the client.rb file
377
+ # config - mixlib-cli settings (accessor from mixlib-cli)
378
+ #
379
+ def merge_configs
380
+ # Update our original_config - if someone has created a knife command
381
+ # instance directly, they are likely ot have set cmd.config values directly
382
+ # as well, at which point our saved original config is no longer up to date.
383
+ @original_config = config.dup
384
+ # other code may have a handle to the config object, so use Hash#replace to deliberately
385
+ # update-in-place.
386
+ config.replace(config_file_defaults.merge(default_config).merge(config_file_settings).merge(config))
387
+ end
388
+
389
+ #
390
+ # Determine the source of a given configuration key
391
+ #
392
+ # @argument key [Symbol] a configuration key
393
+ # @return [Symbol,NilClass] return the source of the config key,
394
+ # one of:
395
+ # - :cli - this was explicitly provided on the CLI
396
+ # - :config - this came from Chef::Config[:knife] explicitly being set
397
+ # - :cli_default - came from a declared CLI `option`'s `default` value.
398
+ # - :config_default - this came from Chef::Config[:knife]'s defaults
399
+ # - nil - if the key could not be found in any source.
400
+ # This can happen when it is invalid, or has been
401
+ # set directly into #config without then calling #merge_config
402
+ def config_source(key)
403
+ return :cli if @original_config.include? key
404
+ return :config if config_file_settings.key? key
405
+ return :cli_default if default_config.include? key
406
+ return :config_default if config_file_defaults.key? key # must come after :config check
407
+
408
+ nil
409
+ end
410
+
411
+ # Catch-all method that does any massaging needed for various config
412
+ # components, such as expanding file paths and converting verbosity level
413
+ # into log level.
414
+ def apply_computed_config
415
+ Chef::Config[:color] = config[:color]
416
+
417
+ # If the verbosity is not set, use what is already present on the log_level config.
418
+ Chef::Config[:log_level] = case Chef::Config[:verbosity]
419
+ when 0
420
+ :warn
421
+ when 1
422
+ :info
423
+ when 2
424
+ :debug
425
+ when nil
426
+ # The default log_level is auto and that is not a valid log_level.
427
+ Chef::Config[:log_level] == :auto ? :warn : Chef::Config[:log_level]
428
+ else
429
+ :trace
430
+ end
431
+
432
+ Chef::Config[:log_level] = :trace if ENV["KNIFE_DEBUG"]
433
+
434
+ Chef::Config[:node_name] = config[:node_name] if config[:node_name]
435
+ Chef::Config[:client_key] = config[:client_key] if config[:client_key]
436
+ Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
437
+ Chef::Config[:environment] = config[:environment] if config[:environment]
438
+
439
+ Chef::Config.local_mode = config[:local_mode] if config.key?(:local_mode)
440
+
441
+ Chef::Config.listen = config[:listen] if config.key?(:listen)
442
+
443
+ if Chef::Config.local_mode && !Chef::Config.key?(:cookbook_path) && !Chef::Config.key?(:chef_repo_path)
444
+ Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
445
+ end
446
+ Chef::Config.chef_zero.host = config[:chef_zero_host] if config[:chef_zero_host]
447
+ Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port]
448
+
449
+ # Expand a relative path from the config directory. Config from command
450
+ # line should already be expanded, and absolute paths will be unchanged.
451
+ if Chef::Config[:client_key] && config[:config_file]
452
+ Chef::Config[:client_key] = File.expand_path(Chef::Config[:client_key], File.dirname(config[:config_file]))
453
+ end
454
+
455
+ Mixlib::Log::Formatter.show_time = false
456
+ Chef::Log.init(Chef::Config[:log_location])
457
+ Chef::Log.level(Chef::Config[:log_level] || :error)
458
+ end
459
+
460
+ def configure_chef
461
+ # knife needs to send logger output to STDERR by default
462
+ Chef::Config[:log_location] = STDERR
463
+ config_loader = self.class.load_config(config[:config_file], config[:profile])
464
+ config[:config_file] = config_loader.config_location
465
+
466
+ # For CLI options like `--config-option key=value`. These have to get
467
+ # parsed and applied separately.
468
+ extra_config_options = config.delete(:config_option)
469
+
470
+ merge_configs
471
+ apply_computed_config
472
+
473
+ # This has to be after apply_computed_config so that Mixlib::Log is configured
474
+ Chef::Log.info("Using configuration from #{config[:config_file]}") if config[:config_file]
475
+
476
+ begin
477
+ Chef::Config.apply_extra_config_options(extra_config_options)
478
+ rescue ChefConfig::UnparsableConfigOption => e
479
+ ui.error e.message
480
+ show_usage
481
+ exit(1)
482
+ end
483
+
484
+ Chef::Config.export_proxies
485
+ end
486
+
487
+ def show_usage
488
+ stdout.puts("USAGE: " + opt_parser.to_s)
489
+ end
490
+
491
+ def run_with_pretty_exceptions(raise_exception = false)
492
+ unless respond_to?(:run)
493
+ ui.error "You need to add a #run method to your knife command before you can use it"
494
+ end
495
+ ENV["PATH"] = default_paths if Chef::Config[:enforce_default_paths] || Chef::Config[:enforce_path_sanity]
496
+ maybe_setup_fips
497
+ Chef::LocalMode.with_server_connectivity do
498
+ run
499
+ end
500
+ rescue Exception => e
501
+ raise if raise_exception || ( Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 2 )
502
+
503
+ humanize_exception(e)
504
+ exit 100
505
+ end
506
+
507
+ def humanize_exception(e)
508
+ case e
509
+ when SystemExit
510
+ raise # make sure exit passes through.
511
+ when Net::HTTPClientException, Net::HTTPFatalError
512
+ humanize_http_exception(e)
513
+ when OpenSSL::SSL::SSLError
514
+ ui.error "Could not establish a secure connection to the server."
515
+ ui.info "Use `knife ssl check` to troubleshoot your SSL configuration."
516
+ ui.info "If your server uses a self-signed certificate, you can use"
517
+ ui.info "`knife ssl fetch` to make knife trust the server's certificates."
518
+ ui.info ""
519
+ ui.info "Original Exception: #{e.class.name}: #{e.message}"
520
+ when Errno::ECONNREFUSED, Timeout::Error, Errno::ETIMEDOUT, SocketError
521
+ ui.error "Network Error: #{e.message}"
522
+ ui.info "Check your knife configuration and network settings"
523
+ when NameError, NoMethodError
524
+ ui.error "knife encountered an unexpected error"
525
+ ui.info "This may be a bug in the '#{self.class.common_name}' knife command or plugin"
526
+ ui.info "Please collect the output of this command with the `-VVV` option before filing a bug report."
527
+ ui.info "Exception: #{e.class.name}: #{e.message}"
528
+ when Chef::Exceptions::PrivateKeyMissing
529
+ ui.error "Your private key could not be loaded from #{api_key}"
530
+ ui.info "Check your configuration file and ensure that your private key is readable"
531
+ when Chef::Exceptions::InvalidRedirect
532
+ ui.error "Invalid Redirect: #{e.message}"
533
+ ui.info "Change your server location in config.rb/knife.rb to the server's FQDN to avoid unwanted redirections."
534
+ else
535
+ ui.error "#{e.class.name}: #{e.message}"
536
+ end
537
+ end
538
+
539
+ def humanize_http_exception(e)
540
+ response = e.response
541
+ case response
542
+ when Net::HTTPUnauthorized
543
+ ui.error "Failed to authenticate to #{server_url} as #{username} with key #{api_key}"
544
+ ui.info "Response: #{format_rest_error(response)}"
545
+ when Net::HTTPForbidden
546
+ ui.error "You authenticated successfully to #{server_url} as #{username} but you are not authorized for this action."
547
+ proxy_env_vars = ENV.to_hash.keys.map(&:downcase) & %w{http_proxy https_proxy ftp_proxy socks_proxy no_proxy}
548
+ unless proxy_env_vars.empty?
549
+ ui.error "There are proxy servers configured, your server url may need to be added to NO_PROXY."
550
+ end
551
+ ui.info "Response: #{format_rest_error(response)}"
552
+ when Net::HTTPBadRequest
553
+ ui.error "The data in your request was invalid"
554
+ ui.info "Response: #{format_rest_error(response)}"
555
+ when Net::HTTPNotFound
556
+ ui.error "The object you are looking for could not be found"
557
+ ui.info "Response: #{format_rest_error(response)}"
558
+ when Net::HTTPInternalServerError
559
+ ui.error "internal server error"
560
+ ui.info "Response: #{format_rest_error(response)}"
561
+ when Net::HTTPBadGateway
562
+ ui.error "bad gateway"
563
+ ui.info "Response: #{format_rest_error(response)}"
564
+ when Net::HTTPServiceUnavailable
565
+ ui.error "Service temporarily unavailable"
566
+ ui.info "Response: #{format_rest_error(response)}"
567
+ when Net::HTTPNotAcceptable
568
+ version_header = Chef::JSONCompat.from_json(response["x-ops-server-api-version"])
569
+ client_api_version = version_header["request_version"]
570
+ min_server_version = version_header["min_version"]
571
+ max_server_version = version_header["max_version"]
572
+ ui.error "The API version that Knife is using is not supported by the server you sent this request to."
573
+ ui.info "The request that Knife sent was using API version #{client_api_version}."
574
+ ui.info "The server you sent the request to supports a min API version of #{min_server_version} and a max API version of #{max_server_version}."
575
+ ui.info "Please either update your #{ChefUtils::Dist::Infra::PRODUCT} or the server to be a compatible set."
576
+ else
577
+ ui.error response.message
578
+ ui.info "Response: #{format_rest_error(response)}"
579
+ end
580
+ end
581
+
582
+ def username
583
+ Chef::Config[:node_name]
584
+ end
585
+
586
+ def api_key
587
+ Chef::Config[:client_key]
588
+ end
589
+
590
+ # Parses JSON from the error response sent by Chef Server and returns the
591
+ # error message
592
+ #--
593
+ # TODO: this code belongs in Chef::REST
594
+ def format_rest_error(response)
595
+ Array(Chef::JSONCompat.from_json(response.body)["error"]).join("; ")
596
+ rescue Exception
597
+ response.body
598
+ end
599
+
600
+ # FIXME: yard with @yield
601
+ def create_object(object, pretty_name = nil, object_class: nil)
602
+ output = if object_class
603
+ edit_data(object, object_class: object_class)
604
+ else
605
+ edit_hash(object)
606
+ end
607
+
608
+ if Kernel.block_given?
609
+ output = yield(output)
610
+ else
611
+ output.save
612
+ end
613
+
614
+ pretty_name ||= output
615
+
616
+ msg("Created #{pretty_name}")
617
+
618
+ output(output) if config[:print_after]
619
+ end
620
+
621
+ # FIXME: yard with @yield
622
+ def delete_object(klass, name, delete_name = nil)
623
+ confirm("Do you really want to delete #{name}")
624
+
625
+ if Kernel.block_given?
626
+ object = yield
627
+ else
628
+ object = klass.load(name)
629
+ object.destroy
630
+ end
631
+
632
+ output(format_for_display(object)) if config[:print_after]
633
+
634
+ obj_name = delete_name ? "#{delete_name}[#{name}]" : object
635
+ msg("Deleted #{obj_name}")
636
+ end
637
+
638
+ # helper method for testing if a field exists
639
+ # and returning the usage and proper error if not
640
+ def test_mandatory_field(field, fieldname)
641
+ if field.nil?
642
+ show_usage
643
+ ui.fatal("You must specify a #{fieldname}")
644
+ exit 1
645
+ end
646
+ end
647
+
648
+ def rest
649
+ @rest ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url])
650
+ end
651
+
652
+ def noauth_rest
653
+ @rest ||= begin
654
+ require "chef/http/simple_json" unless defined?(Chef::HTTP::SimpleJSON)
655
+ Chef::HTTP::SimpleJSON.new(Chef::Config[:chef_server_url])
656
+ end
657
+ end
658
+
659
+ def server_url
660
+ Chef::Config[:chef_server_url]
661
+ end
662
+
663
+ def maybe_setup_fips
664
+ unless config[:fips].nil?
665
+ Chef::Config[:fips] = config[:fips]
666
+ end
667
+ Chef::Config.init_openssl
668
+ end
669
+
670
+ def root_rest
671
+ @root_rest ||= begin
672
+ require "chef/server_api" unless defined? Chef::ServerAPI
673
+ Chef::ServerAPI.new(Chef::Config[:chef_server_root])
674
+ end
675
+ end
676
+ end
677
+ end