knife 18.2.7 → 18.3.0

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 (667) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +26 -26
  3. data/LICENSE +201 -201
  4. data/Rakefile +33 -33
  5. data/bin/knife +24 -24
  6. data/knife.gemspec +62 -62
  7. data/lib/chef/application/knife.rb +234 -234
  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 +242 -242
  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 +1193 -1193
  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 +264 -264
  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 -232
  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 +338 -338
  65. data/lib/chef/knife/core/windows_bootstrap_context.rb +405 -405
  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/list.rb +177 -177
  101. data/lib/chef/knife/node_bulk_delete.rb +75 -75
  102. data/lib/chef/knife/node_create.rb +47 -47
  103. data/lib/chef/knife/node_delete.rb +46 -46
  104. data/lib/chef/knife/node_edit.rb +70 -70
  105. data/lib/chef/knife/node_environment_set.rb +53 -53
  106. data/lib/chef/knife/node_from_file.rb +51 -51
  107. data/lib/chef/knife/node_list.rb +44 -44
  108. data/lib/chef/knife/node_policy_set.rb +79 -79
  109. data/lib/chef/knife/node_run_list_add.rb +104 -104
  110. data/lib/chef/knife/node_run_list_remove.rb +67 -67
  111. data/lib/chef/knife/node_run_list_set.rb +66 -66
  112. data/lib/chef/knife/node_show.rb +63 -63
  113. data/lib/chef/knife/null.rb +12 -12
  114. data/lib/chef/knife/org_create.rb +70 -70
  115. data/lib/chef/knife/org_delete.rb +32 -32
  116. data/lib/chef/knife/org_edit.rb +48 -48
  117. data/lib/chef/knife/org_list.rb +44 -44
  118. data/lib/chef/knife/org_show.rb +31 -31
  119. data/lib/chef/knife/org_user_add.rb +62 -62
  120. data/lib/chef/knife/org_user_remove.rb +103 -103
  121. data/lib/chef/knife/raw.rb +123 -123
  122. data/lib/chef/knife/recipe_list.rb +32 -32
  123. data/lib/chef/knife/rehash.rb +50 -50
  124. data/lib/chef/knife/role_bulk_delete.rb +66 -66
  125. data/lib/chef/knife/role_create.rb +53 -53
  126. data/lib/chef/knife/role_delete.rb +46 -46
  127. data/lib/chef/knife/role_edit.rb +45 -45
  128. data/lib/chef/knife/role_env_run_list_add.rb +87 -87
  129. data/lib/chef/knife/role_env_run_list_clear.rb +55 -55
  130. data/lib/chef/knife/role_env_run_list_remove.rb +57 -57
  131. data/lib/chef/knife/role_env_run_list_replace.rb +60 -60
  132. data/lib/chef/knife/role_env_run_list_set.rb +70 -70
  133. data/lib/chef/knife/role_from_file.rb +51 -51
  134. data/lib/chef/knife/role_list.rb +42 -42
  135. data/lib/chef/knife/role_run_list_add.rb +87 -87
  136. data/lib/chef/knife/role_run_list_clear.rb +55 -55
  137. data/lib/chef/knife/role_run_list_remove.rb +56 -56
  138. data/lib/chef/knife/role_run_list_replace.rb +60 -60
  139. data/lib/chef/knife/role_run_list_set.rb +69 -69
  140. data/lib/chef/knife/role_show.rb +48 -48
  141. data/lib/chef/knife/search.rb +194 -194
  142. data/lib/chef/knife/serve.rb +65 -65
  143. data/lib/chef/knife/show.rb +72 -72
  144. data/lib/chef/knife/ssh.rb +657 -657
  145. data/lib/chef/knife/ssl_check.rb +284 -284
  146. data/lib/chef/knife/ssl_fetch.rb +162 -162
  147. data/lib/chef/knife/status.rb +95 -95
  148. data/lib/chef/knife/supermarket_download.rb +119 -119
  149. data/lib/chef/knife/supermarket_install.rb +192 -192
  150. data/lib/chef/knife/supermarket_list.rb +76 -76
  151. data/lib/chef/knife/supermarket_search.rb +53 -53
  152. data/lib/chef/knife/supermarket_share.rb +166 -166
  153. data/lib/chef/knife/supermarket_show.rb +66 -66
  154. data/lib/chef/knife/supermarket_unshare.rb +62 -62
  155. data/lib/chef/knife/tag_create.rb +52 -52
  156. data/lib/chef/knife/tag_delete.rb +60 -60
  157. data/lib/chef/knife/tag_list.rb +47 -47
  158. data/lib/chef/knife/upload.rb +87 -87
  159. data/lib/chef/knife/user_create.rb +180 -180
  160. data/lib/chef/knife/user_delete.rb +151 -151
  161. data/lib/chef/knife/user_dissociate.rb +42 -42
  162. data/lib/chef/knife/user_edit.rb +94 -94
  163. data/lib/chef/knife/user_invite_add.rb +43 -43
  164. data/lib/chef/knife/user_invite_list.rb +34 -34
  165. data/lib/chef/knife/user_invite_rescind.rb +63 -63
  166. data/lib/chef/knife/user_key_create.rb +73 -73
  167. data/lib/chef/knife/user_key_delete.rb +80 -80
  168. data/lib/chef/knife/user_key_edit.rb +83 -83
  169. data/lib/chef/knife/user_key_list.rb +73 -73
  170. data/lib/chef/knife/user_key_show.rb +80 -80
  171. data/lib/chef/knife/user_list.rb +43 -43
  172. data/lib/chef/knife/user_password.rb +70 -70
  173. data/lib/chef/knife/user_reregister.rb +59 -59
  174. data/lib/chef/knife/user_show.rb +52 -52
  175. data/lib/chef/knife/version.rb +24 -24
  176. data/lib/chef/knife/xargs.rb +282 -282
  177. data/lib/chef/knife/yaml_convert.rb +91 -91
  178. data/lib/chef/knife.rb +673 -673
  179. data/spec/data/apt/chef-integration-test-1.0/debian/changelog +5 -5
  180. data/spec/data/apt/chef-integration-test-1.0/debian/compat +1 -1
  181. data/spec/data/apt/chef-integration-test-1.0/debian/control +13 -13
  182. data/spec/data/apt/chef-integration-test-1.0/debian/copyright +34 -34
  183. data/spec/data/apt/chef-integration-test-1.0/debian/files +1 -1
  184. data/spec/data/apt/chef-integration-test-1.0/debian/rules +13 -13
  185. data/spec/data/apt/chef-integration-test-1.0/debian/source/format +1 -1
  186. data/spec/data/apt/chef-integration-test-1.1/debian/changelog +11 -11
  187. data/spec/data/apt/chef-integration-test-1.1/debian/compat +1 -1
  188. data/spec/data/apt/chef-integration-test-1.1/debian/control +13 -13
  189. data/spec/data/apt/chef-integration-test-1.1/debian/copyright +34 -34
  190. data/spec/data/apt/chef-integration-test-1.1/debian/files +1 -1
  191. data/spec/data/apt/chef-integration-test-1.1/debian/rules +13 -13
  192. data/spec/data/apt/chef-integration-test-1.1/debian/source/format +1 -1
  193. data/spec/data/apt/chef-integration-test2-1.0/debian/changelog +5 -5
  194. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/conffiles +1 -1
  195. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/control +10 -10
  196. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2/DEBIAN/md5sums +1 -1
  197. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.debhelper.log +45 -45
  198. data/spec/data/apt/chef-integration-test2-1.0/debian/chef-integration-test2.substvars +1 -1
  199. data/spec/data/apt/chef-integration-test2-1.0/debian/compat +1 -1
  200. data/spec/data/apt/chef-integration-test2-1.0/debian/conffiles +1 -1
  201. data/spec/data/apt/chef-integration-test2-1.0/debian/control +13 -13
  202. data/spec/data/apt/chef-integration-test2-1.0/debian/copyright +34 -34
  203. data/spec/data/apt/chef-integration-test2-1.0/debian/files +1 -1
  204. data/spec/data/apt/chef-integration-test2-1.0/debian/rules +13 -13
  205. data/spec/data/apt/chef-integration-test2-1.0/debian/source/format +1 -1
  206. data/spec/data/apt/chef-integration-test2_1.0-1.dsc +18 -18
  207. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.build +91 -91
  208. data/spec/data/apt/chef-integration-test2_1.0-1_amd64.changes +31 -31
  209. data/spec/data/apt/chef-integration-test_1.0-1_amd64.changes +22 -22
  210. data/spec/data/apt/chef-integration-test_1.1-1_amd64.changes +22 -22
  211. data/spec/data/apt/var/www/apt/conf/distributions +7 -7
  212. data/spec/data/apt/var/www/apt/conf/incoming +4 -4
  213. data/spec/data/apt/var/www/apt/conf/pulls +3 -3
  214. data/spec/data/apt/var/www/apt/db/version +4 -4
  215. data/spec/data/apt/var/www/apt/dists/sid/Release +19 -19
  216. data/spec/data/apt/var/www/apt/dists/sid/main/binary-amd64/Packages +16 -16
  217. data/spec/data/apt/var/www/apt/dists/sid/main/binary-amd64/Release +5 -5
  218. data/spec/data/bootstrap/encrypted_data_bag_secret +1 -1
  219. data/spec/data/bootstrap/no_proxy.erb +2 -2
  220. data/spec/data/bootstrap/secret.erb +9 -9
  221. data/spec/data/bootstrap/test-hints.erb +12 -12
  222. data/spec/data/bootstrap/test.erb +1 -1
  223. data/spec/data/cb_version_cookbooks/tatft/README.rdoc +2 -2
  224. data/spec/data/cb_version_cookbooks/tatft/attributes/default.rb +1 -1
  225. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-600hhz-0 +1 -1
  226. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ahd2gq-0 +1 -1
  227. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-api8ux-0 +1 -1
  228. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-b0r1m1-0 +1 -1
  229. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-bfygsi-0 +1 -1
  230. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-el14l6-0 +1 -1
  231. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ivrl3y-0 +1 -1
  232. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-kkbs85-0 +1 -1
  233. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ory1ux-0 +1 -1
  234. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-pgsq76-0 +1 -1
  235. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ra8uim-0 +1 -1
  236. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-t7k1g-0 +1 -1
  237. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-t8g0sv-0 +1 -1
  238. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-ufy6g3-0 +1 -1
  239. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-x2d6j9-0 +1 -1
  240. data/spec/data/checksum_cache/chef-file--tmp-chef-rendered-template20100929-10863-xi0l6h-0 +1 -1
  241. data/spec/data/client.d_00/00-foo.rb +2 -2
  242. data/spec/data/client.d_00/01-bar.rb +1 -1
  243. data/spec/data/client.d_00/02-strings.rb +2 -2
  244. data/spec/data/client.d_00/bar +1 -1
  245. data/spec/data/client.d_01/foo/bar.rb +1 -1
  246. data/spec/data/client.d_02/foo.rb/foo.txt +1 -1
  247. data/spec/data/config.rb +6 -6
  248. data/spec/data/cookbooks/angrybash/metadata.rb +2 -2
  249. data/spec/data/cookbooks/angrybash/recipes/default.rb +8 -8
  250. data/spec/data/cookbooks/apache2/files/default/apache2_module_conf_generate.pl +2 -2
  251. data/spec/data/cookbooks/apache2/metadata.json +33 -33
  252. data/spec/data/cookbooks/apache2/metadata.rb +2 -2
  253. data/spec/data/cookbooks/apache2/recipes/default.rb +2 -2
  254. data/spec/data/cookbooks/borken/metadata.rb +2 -2
  255. data/spec/data/cookbooks/borken/recipes/default.rb +1 -1
  256. data/spec/data/cookbooks/borken/templates/default/borken.erb +1 -1
  257. data/spec/data/cookbooks/chefignore +8 -8
  258. data/spec/data/cookbooks/ignorken/files/default/not_me.rb +2 -2
  259. data/spec/data/cookbooks/ignorken/metadata.rb +2 -2
  260. data/spec/data/cookbooks/ignorken/recipes/ignoreme.rb +1 -1
  261. data/spec/data/cookbooks/ignorken/templates/ubuntu-12.10/not_me.rb +2 -2
  262. data/spec/data/cookbooks/irssi/files/default/irssi.response +2 -2
  263. data/spec/data/cookbooks/java/files/default/java.response +1 -1
  264. data/spec/data/cookbooks/java/metadata.json +33 -33
  265. data/spec/data/cookbooks/java/metadata.rb +2 -2
  266. data/spec/data/cookbooks/name-mismatch-versionnumber/README.md +4 -4
  267. data/spec/data/cookbooks/name-mismatch-versionnumber/metadata.rb +8 -8
  268. data/spec/data/cookbooks/name-mismatch-versionnumber/recipes/default.rb +8 -8
  269. data/spec/data/cookbooks/openldap/attributes/default.rb +16 -16
  270. data/spec/data/cookbooks/openldap/attributes/smokey.rb +1 -1
  271. data/spec/data/cookbooks/openldap/definitions/client.rb +5 -5
  272. data/spec/data/cookbooks/openldap/definitions/server.rb +5 -5
  273. data/spec/data/cookbooks/openldap/files/default/.dotfile +1 -1
  274. data/spec/data/cookbooks/openldap/files/default/remotedir/.a_dotdir/.a_dotfile_in_a_dotdir +1 -1
  275. data/spec/data/cookbooks/openldap/files/default/remotedir/not_a_template.erb +2 -2
  276. data/spec/data/cookbooks/openldap/files/default/remotedir/remote_dir_file1.txt +2 -2
  277. data/spec/data/cookbooks/openldap/files/default/remotedir/remote_dir_file2.txt +2 -2
  278. data/spec/data/cookbooks/openldap/files/default/remotedir/remotesubdir/.a_dotfile +1 -1
  279. data/spec/data/cookbooks/openldap/files/default/remotedir/remotesubdir/remote_subdir_file1.txt +2 -2
  280. data/spec/data/cookbooks/openldap/files/default/remotedir/remotesubdir/remote_subdir_file2.txt +2 -2
  281. data/spec/data/cookbooks/openldap/files/default/remotedir/subdir_with_no_file_just_a_subsubdir/the_subsubdir/some_file.txt +3 -3
  282. data/spec/data/cookbooks/openldap/libraries/openldap/version.rb +3 -3
  283. data/spec/data/cookbooks/openldap/libraries/openldap.rb +4 -4
  284. data/spec/data/cookbooks/openldap/metadata.rb +8 -8
  285. data/spec/data/cookbooks/openldap/recipes/default.rb +4 -4
  286. data/spec/data/cookbooks/openldap/recipes/gigantor.rb +3 -3
  287. data/spec/data/cookbooks/openldap/recipes/one.rb +15 -15
  288. data/spec/data/cookbooks/openldap/recipes/return.rb +2 -2
  289. data/spec/data/cookbooks/openldap/templates/default/helper_test.erb +1 -1
  290. data/spec/data/cookbooks/openldap/templates/default/helpers.erb +14 -14
  291. data/spec/data/cookbooks/openldap/templates/default/helpers_via_partial_test.erb +1 -1
  292. data/spec/data/cookbooks/openldap/templates/default/nested_openldap_partials.erb +1 -1
  293. data/spec/data/cookbooks/openldap/templates/default/nested_partial.erb +1 -1
  294. data/spec/data/cookbooks/openldap/templates/default/no_windows_line_endings.erb +4 -4
  295. data/spec/data/cookbooks/openldap/templates/default/openldap_nested_variable_stuff.erb +1 -1
  296. data/spec/data/cookbooks/openldap/templates/default/openldap_variable_stuff.conf.erb +1 -1
  297. data/spec/data/cookbooks/openldap/templates/default/test.erb +1 -1
  298. data/spec/data/cookbooks/preseed/files/default/preseed-file.seed +1 -1
  299. data/spec/data/cookbooks/preseed/files/default/preseed-template.seed +4 -4
  300. data/spec/data/cookbooks/preseed/metadata.rb +2 -2
  301. data/spec/data/cookbooks/preseed/templates/default/preseed-template-variables.seed +1 -1
  302. data/spec/data/cookbooks/preseed/templates/default/preseed-template.seed +1 -1
  303. data/spec/data/cookbooks/starter/chefignore +8 -8
  304. data/spec/data/cookbooks/starter/metadata.rb +2 -2
  305. data/spec/data/cookbooks/starter/recipes/default.rb +4 -4
  306. data/spec/data/cookbooks/supports-platform-constraints/metadata.rb +5 -5
  307. data/spec/data/cookbooks/wget/files/default/wget.response +2 -2
  308. data/spec/data/definitions/test.rb +4 -4
  309. data/spec/data/environment-config.rb +4 -4
  310. data/spec/data/file-providers-method-snapshot-chef-11-4.json +127 -127
  311. data/spec/data/fileedit/hosts +4 -4
  312. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/README.md +4 -4
  313. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/metadata.rb +13 -13
  314. data/spec/data/incomplete-metadata-chef-repo/incomplete-metadata/recipes/default.rb +8 -8
  315. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/README.md +4 -4
  316. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/metadata.rb +9 -9
  317. data/spec/data/invalid-metadata-chef-repo/invalid-metadata/recipes/default.rb +8 -8
  318. data/spec/data/kitchen/chefignore +6 -6
  319. data/spec/data/kitchen/openldap/attributes/default.rb +3 -3
  320. data/spec/data/kitchen/openldap/attributes/robinson.rb +2 -2
  321. data/spec/data/kitchen/openldap/definitions/client.rb +3 -3
  322. data/spec/data/kitchen/openldap/definitions/drewbarrymore.rb +2 -2
  323. data/spec/data/kitchen/openldap/recipes/gigantor.rb +2 -2
  324. data/spec/data/kitchen/openldap/recipes/ignoreme.rb +2 -2
  325. data/spec/data/kitchen/openldap/recipes/woot.rb +3 -3
  326. data/spec/data/knife_subcommand/test_explicit_category.rb +6 -6
  327. data/spec/data/knife_subcommand/test_name_mapping.rb +4 -4
  328. data/spec/data/knife_subcommand/test_yourself.rb +21 -21
  329. data/spec/data/lwrp/providers/buck_passer.rb +28 -28
  330. data/spec/data/lwrp/providers/buck_passer_2.rb +26 -26
  331. data/spec/data/lwrp/providers/embedded_resource_accesses_providers_scope.rb +28 -28
  332. data/spec/data/lwrp/providers/inline_compiler.rb +24 -24
  333. data/spec/data/lwrp/providers/monkey_name_printer.rb +5 -5
  334. data/spec/data/lwrp/providers/paint_drying_watcher.rb +7 -7
  335. data/spec/data/lwrp/providers/thumb_twiddler.rb +7 -7
  336. data/spec/data/lwrp/resources/bar.rb +4 -4
  337. data/spec/data/lwrp/resources/buck_passer.rb +6 -6
  338. data/spec/data/lwrp/resources/buck_passer_2.rb +4 -4
  339. data/spec/data/lwrp/resources/embedded_resource_accesses_providers_scope.rb +4 -4
  340. data/spec/data/lwrp/resources/foo.rb +6 -6
  341. data/spec/data/lwrp/resources/inline_compiler.rb +4 -4
  342. data/spec/data/lwrp/resources/monkey_name_printer.rb +6 -6
  343. data/spec/data/lwrp/resources/paint_drying_watcher.rb +4 -4
  344. data/spec/data/lwrp/resources/thumb_twiddler.rb +4 -4
  345. data/spec/data/lwrp/resources_with_default_attributes/nodeattr.rb +3 -3
  346. data/spec/data/lwrp_const_scoping/resources/conflict.rb +1 -1
  347. data/spec/data/lwrp_override/providers/buck_passer.rb +5 -5
  348. data/spec/data/lwrp_override/resources/foo.rb +11 -11
  349. data/spec/data/mac_users/10.9.plist.xml +560 -560
  350. data/spec/data/mac_users/10.9.shadow.xml +21 -21
  351. data/spec/data/metadata/quick_start/metadata.rb +14 -14
  352. data/spec/data/mixin/invalid_data.rb +3 -3
  353. data/spec/data/mixin/real_data.rb +2 -2
  354. data/spec/data/nested.json +2 -2
  355. data/spec/data/nodes/default.rb +15 -15
  356. data/spec/data/nodes/test.example.com.rb +17 -17
  357. data/spec/data/nodes/test.rb +15 -15
  358. data/spec/data/null_config.rb +1 -1
  359. data/spec/data/object_loader/environments/test.json +7 -7
  360. data/spec/data/object_loader/environments/test.rb +2 -2
  361. data/spec/data/object_loader/environments/test_json_class.json +8 -8
  362. data/spec/data/object_loader/nodes/test.json +7 -7
  363. data/spec/data/object_loader/nodes/test.rb +2 -2
  364. data/spec/data/object_loader/nodes/test_json_class.json +8 -8
  365. data/spec/data/object_loader/roles/test.json +7 -7
  366. data/spec/data/object_loader/roles/test.rb +2 -2
  367. data/spec/data/object_loader/roles/test_json_class.json +8 -8
  368. data/spec/data/partial_one.erb +1 -1
  369. data/spec/data/prefer_metadata_json/metadata.json +51 -51
  370. data/spec/data/prefer_metadata_json/metadata.rb +6 -6
  371. data/spec/data/recipes/test.rb +7 -7
  372. data/spec/data/root_alias_cookbooks/dup_attr/attributes/default.rb +1 -1
  373. data/spec/data/root_alias_cookbooks/dup_attr/attributes.rb +1 -1
  374. data/spec/data/root_alias_cookbooks/dup_attr/metadata.rb +2 -2
  375. data/spec/data/root_alias_cookbooks/dup_attr/recipe.rb +3 -3
  376. data/spec/data/root_alias_cookbooks/dup_recipe/attributes.rb +1 -1
  377. data/spec/data/root_alias_cookbooks/dup_recipe/metadata.rb +2 -2
  378. data/spec/data/root_alias_cookbooks/dup_recipe/recipe.rb +3 -3
  379. data/spec/data/root_alias_cookbooks/dup_recipe/recipes/default.rb +3 -3
  380. data/spec/data/root_alias_cookbooks/simple/attributes.rb +1 -1
  381. data/spec/data/root_alias_cookbooks/simple/metadata.rb +2 -2
  382. data/spec/data/root_alias_cookbooks/simple/recipe.rb +3 -3
  383. data/spec/data/rubygems.org/sexp_processor-info +49 -49
  384. data/spec/data/run_context/cookbooks/circular-dep1/attributes/default.rb +2 -2
  385. data/spec/data/run_context/cookbooks/circular-dep1/definitions/circular_dep1_res.rb +1 -1
  386. data/spec/data/run_context/cookbooks/circular-dep1/libraries/lib.rb +2 -2
  387. data/spec/data/run_context/cookbooks/circular-dep1/metadata.rb +2 -2
  388. data/spec/data/run_context/cookbooks/circular-dep1/providers/provider.rb +1 -1
  389. data/spec/data/run_context/cookbooks/circular-dep1/resources/resource.rb +2 -2
  390. data/spec/data/run_context/cookbooks/circular-dep2/attributes/default.rb +2 -2
  391. data/spec/data/run_context/cookbooks/circular-dep2/definitions/circular_dep2_res.rb +1 -1
  392. data/spec/data/run_context/cookbooks/circular-dep2/libraries/lib.rb +2 -2
  393. data/spec/data/run_context/cookbooks/circular-dep2/metadata.rb +2 -2
  394. data/spec/data/run_context/cookbooks/circular-dep2/providers/provider.rb +1 -1
  395. data/spec/data/run_context/cookbooks/circular-dep2/resources/resource.rb +2 -2
  396. data/spec/data/run_context/cookbooks/dependency1/attributes/aa_first.rb +2 -2
  397. data/spec/data/run_context/cookbooks/dependency1/attributes/default.rb +2 -2
  398. data/spec/data/run_context/cookbooks/dependency1/attributes/unparsed_file +1 -1
  399. data/spec/data/run_context/cookbooks/dependency1/attributes/zz_last.rb +2 -2
  400. data/spec/data/run_context/cookbooks/dependency1/definitions/dependency1_res.rb +1 -1
  401. data/spec/data/run_context/cookbooks/dependency1/definitions/unparsed_file +1 -1
  402. data/spec/data/run_context/cookbooks/dependency1/libraries/lib.rb +2 -2
  403. data/spec/data/run_context/cookbooks/dependency1/libraries/unparsed_file +1 -1
  404. data/spec/data/run_context/cookbooks/dependency1/providers/provider.rb +1 -1
  405. data/spec/data/run_context/cookbooks/dependency1/providers/unparsed_file +1 -1
  406. data/spec/data/run_context/cookbooks/dependency1/recipes/unparsed_file +1 -1
  407. data/spec/data/run_context/cookbooks/dependency1/resources/resource.rb +2 -2
  408. data/spec/data/run_context/cookbooks/dependency1/resources/unparsed_file +1 -1
  409. data/spec/data/run_context/cookbooks/dependency2/attributes/default.rb +2 -2
  410. data/spec/data/run_context/cookbooks/dependency2/definitions/dependency2_res.rb +1 -1
  411. data/spec/data/run_context/cookbooks/dependency2/libraries/lib.rb +2 -2
  412. data/spec/data/run_context/cookbooks/dependency2/providers/provider.rb +1 -1
  413. data/spec/data/run_context/cookbooks/dependency2/resources/resource.rb +2 -2
  414. data/spec/data/run_context/cookbooks/include/recipes/default.rb +24 -24
  415. data/spec/data/run_context/cookbooks/include/recipes/includee.rb +3 -3
  416. data/spec/data/run_context/cookbooks/no-default-attr/attributes/server.rb +2 -2
  417. data/spec/data/run_context/cookbooks/no-default-attr/definitions/no_default-attr_res.rb +1 -1
  418. data/spec/data/run_context/cookbooks/no-default-attr/providers/provider.rb +1 -1
  419. data/spec/data/run_context/cookbooks/no-default-attr/resources/resource.rb +2 -2
  420. data/spec/data/run_context/cookbooks/test/attributes/george.rb +1 -1
  421. data/spec/data/run_context/cookbooks/test/definitions/new_animals.rb +9 -9
  422. data/spec/data/run_context/cookbooks/test/definitions/new_cat.rb +5 -5
  423. data/spec/data/run_context/cookbooks/test/definitions/test_res.rb +1 -1
  424. data/spec/data/run_context/cookbooks/test/providers/provider.rb +1 -1
  425. data/spec/data/run_context/cookbooks/test/recipes/default.rb +5 -5
  426. data/spec/data/run_context/cookbooks/test/recipes/one.rb +7 -7
  427. data/spec/data/run_context/cookbooks/test/recipes/two.rb +7 -7
  428. data/spec/data/run_context/cookbooks/test/resources/resource.rb +3 -3
  429. data/spec/data/run_context/cookbooks/test-with-circular-deps/attributes/default.rb +2 -2
  430. data/spec/data/run_context/cookbooks/test-with-circular-deps/definitions/test_with-circular-deps_res.rb +1 -1
  431. data/spec/data/run_context/cookbooks/test-with-circular-deps/libraries/lib.rb +2 -2
  432. data/spec/data/run_context/cookbooks/test-with-circular-deps/metadata.rb +2 -2
  433. data/spec/data/run_context/cookbooks/test-with-circular-deps/providers/provider.rb +1 -1
  434. data/spec/data/run_context/cookbooks/test-with-circular-deps/resources/resource.rb +3 -3
  435. data/spec/data/run_context/cookbooks/test-with-deps/attributes/default.rb +2 -2
  436. data/spec/data/run_context/cookbooks/test-with-deps/definitions/test_with-deps_res.rb +1 -1
  437. data/spec/data/run_context/cookbooks/test-with-deps/libraries/lib.rb +1 -1
  438. data/spec/data/run_context/cookbooks/test-with-deps/metadata.rb +3 -3
  439. data/spec/data/run_context/cookbooks/test-with-deps/providers/provider.rb +1 -1
  440. data/spec/data/run_context/cookbooks/test-with-deps/resources/resource.rb +2 -2
  441. data/spec/data/run_context/nodes/run_context.rb +5 -5
  442. data/spec/data/sample_msu1.xml +10 -10
  443. data/spec/data/sample_msu2.xml +14 -14
  444. data/spec/data/sample_msu3.xml +16 -16
  445. data/spec/data/search_queries_to_transform.txt +98 -98
  446. data/spec/data/shef-config.rb +11 -11
  447. data/spec/data/snap_package/async_result_success.json +6 -6
  448. data/spec/data/snap_package/change_id_result.json +175 -175
  449. data/spec/data/snap_package/find_result_failure.json +10 -10
  450. data/spec/data/snap_package/find_result_success.json +70 -70
  451. data/spec/data/snap_package/get_by_name_result_failure.json +10 -10
  452. data/spec/data/snap_package/get_by_name_result_success.json +38 -38
  453. data/spec/data/snap_package/get_conf_success.json +10 -10
  454. data/spec/data/snap_package/result_failure.json +9 -9
  455. data/spec/data/ssl/5e707473.0 +18 -18
  456. data/spec/data/ssl/chef-rspec.cert +27 -27
  457. data/spec/data/ssl/chef-rspec.key +27 -27
  458. data/spec/data/ssl/key.pem +15 -15
  459. data/spec/data/ssl/private_key.pem +27 -27
  460. data/spec/data/ssl/private_key_with_whitespace.pem +32 -32
  461. data/spec/data/standalone_cookbook/chefignore +9 -9
  462. data/spec/data/standalone_cookbook/recipes/default.rb +2 -2
  463. data/spec/data/templates/failed.erb +5 -5
  464. data/spec/data/trusted_certs/example.crt +22 -22
  465. data/spec/data/trusted_certs/example_no_cn.crt +36 -36
  466. data/spec/data/trusted_certs/intermediate.pem +27 -27
  467. data/spec/data/trusted_certs/opscode.pem +57 -57
  468. data/spec/data/trusted_certs/root.pem +22 -22
  469. data/spec/data/windows_certificates/base64_test.cer +20 -20
  470. data/spec/data/windows_certificates/othertest.cer +20 -20
  471. data/spec/data/windows_certificates/test.cer +20 -20
  472. data/spec/data/windows_certificates/test.pem +20 -20
  473. data/spec/functional/configure_spec.rb +33 -33
  474. data/spec/functional/cookbook_delete_spec.rb +156 -156
  475. data/spec/functional/exec_spec.rb +55 -55
  476. data/spec/functional/rehash_spec.rb +39 -39
  477. data/spec/functional/smoke_test.rb +42 -42
  478. data/spec/functional/ssh_spec.rb +352 -352
  479. data/spec/functional/version_spec.rb +26 -26
  480. data/spec/integration/chef_fs_data_store_spec.rb +557 -557
  481. data/spec/integration/chef_repo_path_spec.rb +962 -962
  482. data/spec/integration/chef_repository_file_system_spec.rb +200 -200
  483. data/spec/integration/chefignore_spec.rb +301 -301
  484. data/spec/integration/client_bulk_delete_spec.rb +131 -131
  485. data/spec/integration/client_create_spec.rb +70 -70
  486. data/spec/integration/client_delete_spec.rb +64 -64
  487. data/spec/integration/client_key_create_spec.rb +66 -66
  488. data/spec/integration/client_key_delete_spec.rb +43 -43
  489. data/spec/integration/client_key_list_spec.rb +61 -61
  490. data/spec/integration/client_key_show_spec.rb +45 -45
  491. data/spec/integration/client_list_spec.rb +49 -49
  492. data/spec/integration/client_show_spec.rb +37 -37
  493. data/spec/integration/commands_spec.rb +55 -55
  494. data/spec/integration/common_options_spec.rb +174 -174
  495. data/spec/integration/config_list_spec.rb +220 -220
  496. data/spec/integration/config_show_spec.rb +192 -192
  497. data/spec/integration/config_use_spec.rb +198 -198
  498. data/spec/integration/cookbook_api_ipv6_spec.rb +113 -113
  499. data/spec/integration/cookbook_bulk_delete_spec.rb +65 -65
  500. data/spec/integration/cookbook_download_spec.rb +72 -72
  501. data/spec/integration/cookbook_list_spec.rb +55 -55
  502. data/spec/integration/cookbook_show_spec.rb +149 -149
  503. data/spec/integration/cookbook_upload_spec.rb +128 -128
  504. data/spec/integration/data_bag_create_spec.rb +125 -125
  505. data/spec/integration/data_bag_delete_spec.rb +59 -59
  506. data/spec/integration/data_bag_edit_spec.rb +105 -105
  507. data/spec/integration/data_bag_from_file_spec.rb +116 -116
  508. data/spec/integration/data_bag_list_spec.rb +44 -44
  509. data/spec/integration/data_bag_show_spec.rb +95 -95
  510. data/spec/integration/delete_spec.rb +1018 -1018
  511. data/spec/integration/deps_spec.rb +703 -703
  512. data/spec/integration/diff_spec.rb +605 -605
  513. data/spec/integration/download_spec.rb +1336 -1336
  514. data/spec/integration/environment_compare_spec.rb +75 -75
  515. data/spec/integration/environment_create_spec.rb +41 -41
  516. data/spec/integration/environment_delete_spec.rb +37 -37
  517. data/spec/integration/environment_from_file_spec.rb +116 -116
  518. data/spec/integration/environment_list_spec.rb +42 -42
  519. data/spec/integration/environment_show_spec.rb +77 -77
  520. data/spec/integration/list_spec.rb +1060 -1060
  521. data/spec/integration/node_bulk_delete_spec.rb +52 -52
  522. data/spec/integration/node_create_spec.rb +47 -47
  523. data/spec/integration/node_delete_spec.rb +48 -48
  524. data/spec/integration/node_environment_set_spec.rb +46 -46
  525. data/spec/integration/node_from_file_spec.rb +59 -59
  526. data/spec/integration/node_list_spec.rb +45 -45
  527. data/spec/integration/node_run_list_add_spec.rb +54 -54
  528. data/spec/integration/node_run_list_remove_spec.rb +36 -36
  529. data/spec/integration/node_run_list_set_spec.rb +41 -41
  530. data/spec/integration/node_show_spec.rb +36 -36
  531. data/spec/integration/raw_spec.rb +297 -297
  532. data/spec/integration/redirection_spec.rb +64 -64
  533. data/spec/integration/role_bulk_delete_spec.rb +52 -52
  534. data/spec/integration/role_create_spec.rb +41 -41
  535. data/spec/integration/role_delete_spec.rb +48 -48
  536. data/spec/integration/role_from_file_spec.rb +96 -96
  537. data/spec/integration/role_list_spec.rb +45 -45
  538. data/spec/integration/role_show_spec.rb +51 -51
  539. data/spec/integration/search_node_spec.rb +40 -40
  540. data/spec/integration/serve_spec.rb +92 -92
  541. data/spec/integration/show_spec.rb +197 -197
  542. data/spec/integration/upload_spec.rb +1616 -1616
  543. data/spec/knife_spec_helper.rb +241 -241
  544. data/spec/support/chef_helpers.rb +79 -79
  545. data/spec/support/key_helpers.rb +102 -102
  546. data/spec/support/platform_helpers.rb +255 -255
  547. data/spec/support/platforms/prof/gc.rb +51 -51
  548. data/spec/support/platforms/prof/win32.rb +45 -45
  549. data/spec/support/platforms/win32/spec_service.rb +57 -57
  550. data/spec/support/recipe_dsl_helper.rb +83 -83
  551. data/spec/support/shared/context/config.rb +18 -18
  552. data/spec/support/shared/functional/knife.rb +37 -37
  553. data/spec/support/shared/integration/integration_helper.rb +122 -122
  554. data/spec/support/shared/integration/knife_support.rb +192 -192
  555. data/spec/support/shared/matchers/exit_with_code.rb +32 -32
  556. data/spec/support/shared/matchers/match_environment_variable.rb +17 -17
  557. data/spec/support/shared/unit/knife_shared.rb +39 -39
  558. data/spec/support/shared/unit/mock_shellout.rb +49 -49
  559. data/spec/tiny_server.rb +190 -190
  560. data/spec/unit/application/knife_spec.rb +241 -241
  561. data/spec/unit/knife/bootstrap/chef_vault_handler_spec.rb +152 -152
  562. data/spec/unit/knife/bootstrap/client_builder_spec.rb +207 -207
  563. data/spec/unit/knife/bootstrap/train_connector_spec.rb +244 -244
  564. data/spec/unit/knife/bootstrap_spec.rb +2288 -2233
  565. data/spec/unit/knife/client_bulk_delete_spec.rb +166 -166
  566. data/spec/unit/knife/client_create_spec.rb +232 -232
  567. data/spec/unit/knife/client_delete_spec.rb +99 -99
  568. data/spec/unit/knife/client_edit_spec.rb +53 -53
  569. data/spec/unit/knife/client_list_spec.rb +34 -34
  570. data/spec/unit/knife/client_reregister_spec.rb +62 -62
  571. data/spec/unit/knife/client_show_spec.rb +52 -52
  572. data/spec/unit/knife/configure_client_spec.rb +81 -81
  573. data/spec/unit/knife/configure_spec.rb +190 -190
  574. data/spec/unit/knife/cookbook_bulk_delete_spec.rb +87 -87
  575. data/spec/unit/knife/cookbook_delete_spec.rb +239 -239
  576. data/spec/unit/knife/cookbook_download_spec.rb +255 -255
  577. data/spec/unit/knife/cookbook_list_spec.rb +88 -88
  578. data/spec/unit/knife/cookbook_metadata_from_file_spec.rb +72 -72
  579. data/spec/unit/knife/cookbook_metadata_spec.rb +182 -182
  580. data/spec/unit/knife/cookbook_show_spec.rb +253 -253
  581. data/spec/unit/knife/cookbook_upload_spec.rb +426 -426
  582. data/spec/unit/knife/core/bootstrap_context_spec.rb +287 -287
  583. data/spec/unit/knife/core/cookbook_scm_repo_spec.rb +187 -187
  584. data/spec/unit/knife/core/cookbook_site_streaming_uploader_spec.rb +198 -198
  585. data/spec/unit/knife/core/gem_glob_loader_spec.rb +242 -242
  586. data/spec/unit/knife/core/hashed_command_loader_spec.rb +112 -112
  587. data/spec/unit/knife/core/node_editor_spec.rb +211 -211
  588. data/spec/unit/knife/core/object_loader_spec.rb +81 -81
  589. data/spec/unit/knife/core/status_presenter_spec.rb +54 -54
  590. data/spec/unit/knife/core/subcommand_loader_spec.rb +64 -64
  591. data/spec/unit/knife/core/ui_spec.rb +656 -656
  592. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +238 -238
  593. data/spec/unit/knife/data_bag_create_spec.rb +175 -175
  594. data/spec/unit/knife/data_bag_edit_spec.rb +126 -126
  595. data/spec/unit/knife/data_bag_from_file_spec.rb +174 -174
  596. data/spec/unit/knife/data_bag_secret_options_spec.rb +173 -173
  597. data/spec/unit/knife/data_bag_show_spec.rb +139 -139
  598. data/spec/unit/knife/environment_compare_spec.rb +112 -112
  599. data/spec/unit/knife/environment_create_spec.rb +91 -91
  600. data/spec/unit/knife/environment_delete_spec.rb +71 -71
  601. data/spec/unit/knife/environment_edit_spec.rb +79 -79
  602. data/spec/unit/knife/environment_from_file_spec.rb +90 -90
  603. data/spec/unit/knife/environment_list_spec.rb +54 -54
  604. data/spec/unit/knife/environment_show_spec.rb +52 -52
  605. data/spec/unit/knife/key_create_spec.rb +223 -223
  606. data/spec/unit/knife/key_delete_spec.rb +133 -133
  607. data/spec/unit/knife/key_edit_spec.rb +264 -264
  608. data/spec/unit/knife/key_helper.rb +74 -74
  609. data/spec/unit/knife/key_list_spec.rb +216 -216
  610. data/spec/unit/knife/key_show_spec.rb +126 -126
  611. data/spec/unit/knife/node_bulk_delete_spec.rb +94 -94
  612. data/spec/unit/knife/node_delete_spec.rb +77 -77
  613. data/spec/unit/knife/node_edit_spec.rb +116 -116
  614. data/spec/unit/knife/node_environment_set_spec.rb +61 -61
  615. data/spec/unit/knife/node_from_file_spec.rb +59 -59
  616. data/spec/unit/knife/node_list_spec.rb +62 -62
  617. data/spec/unit/knife/node_policy_set_spec.rb +122 -122
  618. data/spec/unit/knife/node_run_list_add_spec.rb +145 -145
  619. data/spec/unit/knife/node_run_list_remove_spec.rb +106 -106
  620. data/spec/unit/knife/node_run_list_set_spec.rb +115 -115
  621. data/spec/unit/knife/node_show_spec.rb +65 -65
  622. data/spec/unit/knife/org_create_spec.rb +76 -76
  623. data/spec/unit/knife/org_delete_spec.rb +41 -41
  624. data/spec/unit/knife/org_edit_spec.rb +49 -49
  625. data/spec/unit/knife/org_list_spec.rb +58 -58
  626. data/spec/unit/knife/org_show_spec.rb +45 -45
  627. data/spec/unit/knife/org_user_add_spec.rb +39 -39
  628. data/spec/unit/knife/raw_spec.rb +43 -43
  629. data/spec/unit/knife/role_bulk_delete_spec.rb +80 -80
  630. data/spec/unit/knife/role_create_spec.rb +80 -80
  631. data/spec/unit/knife/role_delete_spec.rb +67 -67
  632. data/spec/unit/knife/role_edit_spec.rb +77 -77
  633. data/spec/unit/knife/role_env_run_list_add_spec.rb +217 -217
  634. data/spec/unit/knife/role_env_run_list_clear_spec.rb +94 -94
  635. data/spec/unit/knife/role_env_run_list_remove_spec.rb +102 -102
  636. data/spec/unit/knife/role_env_run_list_replace_spec.rb +105 -105
  637. data/spec/unit/knife/role_env_run_list_set_spec.rb +99 -99
  638. data/spec/unit/knife/role_from_file_spec.rb +69 -69
  639. data/spec/unit/knife/role_list_spec.rb +54 -54
  640. data/spec/unit/knife/role_run_list_add_spec.rb +179 -179
  641. data/spec/unit/knife/role_run_list_clear_spec.rb +84 -84
  642. data/spec/unit/knife/role_run_list_remove_spec.rb +92 -92
  643. data/spec/unit/knife/role_run_list_replace_spec.rb +98 -98
  644. data/spec/unit/knife/role_run_list_set_spec.rb +89 -89
  645. data/spec/unit/knife/role_show_spec.rb +59 -59
  646. data/spec/unit/knife/ssh_spec.rb +403 -403
  647. data/spec/unit/knife/ssl_check_spec.rb +256 -256
  648. data/spec/unit/knife/ssl_fetch_spec.rb +222 -222
  649. data/spec/unit/knife/status_spec.rb +112 -112
  650. data/spec/unit/knife/supermarket_download_spec.rb +152 -152
  651. data/spec/unit/knife/supermarket_install_spec.rb +203 -203
  652. data/spec/unit/knife/supermarket_list_spec.rb +70 -70
  653. data/spec/unit/knife/supermarket_search_spec.rb +85 -85
  654. data/spec/unit/knife/supermarket_share_spec.rb +208 -208
  655. data/spec/unit/knife/supermarket_unshare_spec.rb +78 -78
  656. data/spec/unit/knife/tag_create_spec.rb +23 -23
  657. data/spec/unit/knife/tag_delete_spec.rb +25 -25
  658. data/spec/unit/knife/tag_list_spec.rb +23 -23
  659. data/spec/unit/knife/user_create_spec.rb +282 -282
  660. data/spec/unit/knife/user_delete_spec.rb +171 -171
  661. data/spec/unit/knife/user_edit_spec.rb +54 -54
  662. data/spec/unit/knife/user_list_spec.rb +73 -73
  663. data/spec/unit/knife/user_password_spec.rb +64 -64
  664. data/spec/unit/knife/user_reregister_spec.rb +56 -56
  665. data/spec/unit/knife/user_show_spec.rb +91 -91
  666. data/spec/unit/knife_spec.rb +634 -634
  667. metadata +5 -5
data/lib/chef/knife.rb CHANGED
@@ -1,673 +1,673 @@
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
- case Chef::Config[:verbosity]
418
- when 0, nil
419
- Chef::Config[:log_level] = :warn
420
- when 1
421
- Chef::Config[:log_level] = :info
422
- when 2
423
- Chef::Config[:log_level] = :debug
424
- else
425
- Chef::Config[:log_level] = :trace
426
- end
427
-
428
- Chef::Config[:log_level] = :trace if ENV["KNIFE_DEBUG"]
429
-
430
- Chef::Config[:node_name] = config[:node_name] if config[:node_name]
431
- Chef::Config[:client_key] = config[:client_key] if config[:client_key]
432
- Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
433
- Chef::Config[:environment] = config[:environment] if config[:environment]
434
-
435
- Chef::Config.local_mode = config[:local_mode] if config.key?(:local_mode)
436
-
437
- Chef::Config.listen = config[:listen] if config.key?(:listen)
438
-
439
- if Chef::Config.local_mode && !Chef::Config.key?(:cookbook_path) && !Chef::Config.key?(:chef_repo_path)
440
- Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
441
- end
442
- Chef::Config.chef_zero.host = config[:chef_zero_host] if config[:chef_zero_host]
443
- Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port]
444
-
445
- # Expand a relative path from the config directory. Config from command
446
- # line should already be expanded, and absolute paths will be unchanged.
447
- if Chef::Config[:client_key] && config[:config_file]
448
- Chef::Config[:client_key] = File.expand_path(Chef::Config[:client_key], File.dirname(config[:config_file]))
449
- end
450
-
451
- Mixlib::Log::Formatter.show_time = false
452
- Chef::Log.init(Chef::Config[:log_location])
453
- Chef::Log.level(Chef::Config[:log_level] || :error)
454
- end
455
-
456
- def configure_chef
457
- # knife needs to send logger output to STDERR by default
458
- Chef::Config[:log_location] = STDERR
459
- config_loader = self.class.load_config(config[:config_file], config[:profile])
460
- config[:config_file] = config_loader.config_location
461
-
462
- # For CLI options like `--config-option key=value`. These have to get
463
- # parsed and applied separately.
464
- extra_config_options = config.delete(:config_option)
465
-
466
- merge_configs
467
- apply_computed_config
468
-
469
- # This has to be after apply_computed_config so that Mixlib::Log is configured
470
- Chef::Log.info("Using configuration from #{config[:config_file]}") if config[:config_file]
471
-
472
- begin
473
- Chef::Config.apply_extra_config_options(extra_config_options)
474
- rescue ChefConfig::UnparsableConfigOption => e
475
- ui.error e.message
476
- show_usage
477
- exit(1)
478
- end
479
-
480
- Chef::Config.export_proxies
481
- end
482
-
483
- def show_usage
484
- stdout.puts("USAGE: " + opt_parser.to_s)
485
- end
486
-
487
- def run_with_pretty_exceptions(raise_exception = false)
488
- unless respond_to?(:run)
489
- ui.error "You need to add a #run method to your knife command before you can use it"
490
- end
491
- ENV["PATH"] = default_paths if Chef::Config[:enforce_default_paths] || Chef::Config[:enforce_path_sanity]
492
- maybe_setup_fips
493
- Chef::LocalMode.with_server_connectivity do
494
- run
495
- end
496
- rescue Exception => e
497
- raise if raise_exception || ( Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 2 )
498
-
499
- humanize_exception(e)
500
- exit 100
501
- end
502
-
503
- def humanize_exception(e)
504
- case e
505
- when SystemExit
506
- raise # make sure exit passes through.
507
- when Net::HTTPClientException, Net::HTTPFatalError
508
- humanize_http_exception(e)
509
- when OpenSSL::SSL::SSLError
510
- ui.error "Could not establish a secure connection to the server."
511
- ui.info "Use `knife ssl check` to troubleshoot your SSL configuration."
512
- ui.info "If your server uses a self-signed certificate, you can use"
513
- ui.info "`knife ssl fetch` to make knife trust the server's certificates."
514
- ui.info ""
515
- ui.info "Original Exception: #{e.class.name}: #{e.message}"
516
- when Errno::ECONNREFUSED, Timeout::Error, Errno::ETIMEDOUT, SocketError
517
- ui.error "Network Error: #{e.message}"
518
- ui.info "Check your knife configuration and network settings"
519
- when NameError, NoMethodError
520
- ui.error "knife encountered an unexpected error"
521
- ui.info "This may be a bug in the '#{self.class.common_name}' knife command or plugin"
522
- ui.info "Please collect the output of this command with the `-VVV` option before filing a bug report."
523
- ui.info "Exception: #{e.class.name}: #{e.message}"
524
- when Chef::Exceptions::PrivateKeyMissing
525
- ui.error "Your private key could not be loaded from #{api_key}"
526
- ui.info "Check your configuration file and ensure that your private key is readable"
527
- when Chef::Exceptions::InvalidRedirect
528
- ui.error "Invalid Redirect: #{e.message}"
529
- ui.info "Change your server location in config.rb/knife.rb to the server's FQDN to avoid unwanted redirections."
530
- else
531
- ui.error "#{e.class.name}: #{e.message}"
532
- end
533
- end
534
-
535
- def humanize_http_exception(e)
536
- response = e.response
537
- case response
538
- when Net::HTTPUnauthorized
539
- ui.error "Failed to authenticate to #{server_url} as #{username} with key #{api_key}"
540
- ui.info "Response: #{format_rest_error(response)}"
541
- when Net::HTTPForbidden
542
- ui.error "You authenticated successfully to #{server_url} as #{username} but you are not authorized for this action."
543
- proxy_env_vars = ENV.to_hash.keys.map(&:downcase) & %w{http_proxy https_proxy ftp_proxy socks_proxy no_proxy}
544
- unless proxy_env_vars.empty?
545
- ui.error "There are proxy servers configured, your server url may need to be added to NO_PROXY."
546
- end
547
- ui.info "Response: #{format_rest_error(response)}"
548
- when Net::HTTPBadRequest
549
- ui.error "The data in your request was invalid"
550
- ui.info "Response: #{format_rest_error(response)}"
551
- when Net::HTTPNotFound
552
- ui.error "The object you are looking for could not be found"
553
- ui.info "Response: #{format_rest_error(response)}"
554
- when Net::HTTPInternalServerError
555
- ui.error "internal server error"
556
- ui.info "Response: #{format_rest_error(response)}"
557
- when Net::HTTPBadGateway
558
- ui.error "bad gateway"
559
- ui.info "Response: #{format_rest_error(response)}"
560
- when Net::HTTPServiceUnavailable
561
- ui.error "Service temporarily unavailable"
562
- ui.info "Response: #{format_rest_error(response)}"
563
- when Net::HTTPNotAcceptable
564
- version_header = Chef::JSONCompat.from_json(response["x-ops-server-api-version"])
565
- client_api_version = version_header["request_version"]
566
- min_server_version = version_header["min_version"]
567
- max_server_version = version_header["max_version"]
568
- ui.error "The API version that Knife is using is not supported by the server you sent this request to."
569
- ui.info "The request that Knife sent was using API version #{client_api_version}."
570
- 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}."
571
- ui.info "Please either update your #{ChefUtils::Dist::Infra::PRODUCT} or the server to be a compatible set."
572
- else
573
- ui.error response.message
574
- ui.info "Response: #{format_rest_error(response)}"
575
- end
576
- end
577
-
578
- def username
579
- Chef::Config[:node_name]
580
- end
581
-
582
- def api_key
583
- Chef::Config[:client_key]
584
- end
585
-
586
- # Parses JSON from the error response sent by Chef Server and returns the
587
- # error message
588
- #--
589
- # TODO: this code belongs in Chef::REST
590
- def format_rest_error(response)
591
- Array(Chef::JSONCompat.from_json(response.body)["error"]).join("; ")
592
- rescue Exception
593
- response.body
594
- end
595
-
596
- # FIXME: yard with @yield
597
- def create_object(object, pretty_name = nil, object_class: nil)
598
- output = if object_class
599
- edit_data(object, object_class: object_class)
600
- else
601
- edit_hash(object)
602
- end
603
-
604
- if Kernel.block_given?
605
- output = yield(output)
606
- else
607
- output.save
608
- end
609
-
610
- pretty_name ||= output
611
-
612
- msg("Created #{pretty_name}")
613
-
614
- output(output) if config[:print_after]
615
- end
616
-
617
- # FIXME: yard with @yield
618
- def delete_object(klass, name, delete_name = nil)
619
- confirm("Do you really want to delete #{name}")
620
-
621
- if Kernel.block_given?
622
- object = yield
623
- else
624
- object = klass.load(name)
625
- object.destroy
626
- end
627
-
628
- output(format_for_display(object)) if config[:print_after]
629
-
630
- obj_name = delete_name ? "#{delete_name}[#{name}]" : object
631
- msg("Deleted #{obj_name}")
632
- end
633
-
634
- # helper method for testing if a field exists
635
- # and returning the usage and proper error if not
636
- def test_mandatory_field(field, fieldname)
637
- if field.nil?
638
- show_usage
639
- ui.fatal("You must specify a #{fieldname}")
640
- exit 1
641
- end
642
- end
643
-
644
- def rest
645
- @rest ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url])
646
- end
647
-
648
- def noauth_rest
649
- @rest ||= begin
650
- require "chef/http/simple_json" unless defined?(Chef::HTTP::SimpleJSON)
651
- Chef::HTTP::SimpleJSON.new(Chef::Config[:chef_server_url])
652
- end
653
- end
654
-
655
- def server_url
656
- Chef::Config[:chef_server_url]
657
- end
658
-
659
- def maybe_setup_fips
660
- unless config[:fips].nil?
661
- Chef::Config[:fips] = config[:fips]
662
- end
663
- Chef::Config.init_openssl
664
- end
665
-
666
- def root_rest
667
- @root_rest ||= begin
668
- require "chef/server_api" unless defined? Chef::ServerAPI
669
- Chef::ServerAPI.new(Chef::Config[:chef_server_root])
670
- end
671
- end
672
- end
673
- 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
+ case Chef::Config[:verbosity]
418
+ when 0, nil
419
+ Chef::Config[:log_level] = :warn
420
+ when 1
421
+ Chef::Config[:log_level] = :info
422
+ when 2
423
+ Chef::Config[:log_level] = :debug
424
+ else
425
+ Chef::Config[:log_level] = :trace
426
+ end
427
+
428
+ Chef::Config[:log_level] = :trace if ENV["KNIFE_DEBUG"]
429
+
430
+ Chef::Config[:node_name] = config[:node_name] if config[:node_name]
431
+ Chef::Config[:client_key] = config[:client_key] if config[:client_key]
432
+ Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
433
+ Chef::Config[:environment] = config[:environment] if config[:environment]
434
+
435
+ Chef::Config.local_mode = config[:local_mode] if config.key?(:local_mode)
436
+
437
+ Chef::Config.listen = config[:listen] if config.key?(:listen)
438
+
439
+ if Chef::Config.local_mode && !Chef::Config.key?(:cookbook_path) && !Chef::Config.key?(:chef_repo_path)
440
+ Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
441
+ end
442
+ Chef::Config.chef_zero.host = config[:chef_zero_host] if config[:chef_zero_host]
443
+ Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port]
444
+
445
+ # Expand a relative path from the config directory. Config from command
446
+ # line should already be expanded, and absolute paths will be unchanged.
447
+ if Chef::Config[:client_key] && config[:config_file]
448
+ Chef::Config[:client_key] = File.expand_path(Chef::Config[:client_key], File.dirname(config[:config_file]))
449
+ end
450
+
451
+ Mixlib::Log::Formatter.show_time = false
452
+ Chef::Log.init(Chef::Config[:log_location])
453
+ Chef::Log.level(Chef::Config[:log_level] || :error)
454
+ end
455
+
456
+ def configure_chef
457
+ # knife needs to send logger output to STDERR by default
458
+ Chef::Config[:log_location] = STDERR
459
+ config_loader = self.class.load_config(config[:config_file], config[:profile])
460
+ config[:config_file] = config_loader.config_location
461
+
462
+ # For CLI options like `--config-option key=value`. These have to get
463
+ # parsed and applied separately.
464
+ extra_config_options = config.delete(:config_option)
465
+
466
+ merge_configs
467
+ apply_computed_config
468
+
469
+ # This has to be after apply_computed_config so that Mixlib::Log is configured
470
+ Chef::Log.info("Using configuration from #{config[:config_file]}") if config[:config_file]
471
+
472
+ begin
473
+ Chef::Config.apply_extra_config_options(extra_config_options)
474
+ rescue ChefConfig::UnparsableConfigOption => e
475
+ ui.error e.message
476
+ show_usage
477
+ exit(1)
478
+ end
479
+
480
+ Chef::Config.export_proxies
481
+ end
482
+
483
+ def show_usage
484
+ stdout.puts("USAGE: " + opt_parser.to_s)
485
+ end
486
+
487
+ def run_with_pretty_exceptions(raise_exception = false)
488
+ unless respond_to?(:run)
489
+ ui.error "You need to add a #run method to your knife command before you can use it"
490
+ end
491
+ ENV["PATH"] = default_paths if Chef::Config[:enforce_default_paths] || Chef::Config[:enforce_path_sanity]
492
+ maybe_setup_fips
493
+ Chef::LocalMode.with_server_connectivity do
494
+ run
495
+ end
496
+ rescue Exception => e
497
+ raise if raise_exception || ( Chef::Config[:verbosity] && Chef::Config[:verbosity] >= 2 )
498
+
499
+ humanize_exception(e)
500
+ exit 100
501
+ end
502
+
503
+ def humanize_exception(e)
504
+ case e
505
+ when SystemExit
506
+ raise # make sure exit passes through.
507
+ when Net::HTTPClientException, Net::HTTPFatalError
508
+ humanize_http_exception(e)
509
+ when OpenSSL::SSL::SSLError
510
+ ui.error "Could not establish a secure connection to the server."
511
+ ui.info "Use `knife ssl check` to troubleshoot your SSL configuration."
512
+ ui.info "If your server uses a self-signed certificate, you can use"
513
+ ui.info "`knife ssl fetch` to make knife trust the server's certificates."
514
+ ui.info ""
515
+ ui.info "Original Exception: #{e.class.name}: #{e.message}"
516
+ when Errno::ECONNREFUSED, Timeout::Error, Errno::ETIMEDOUT, SocketError
517
+ ui.error "Network Error: #{e.message}"
518
+ ui.info "Check your knife configuration and network settings"
519
+ when NameError, NoMethodError
520
+ ui.error "knife encountered an unexpected error"
521
+ ui.info "This may be a bug in the '#{self.class.common_name}' knife command or plugin"
522
+ ui.info "Please collect the output of this command with the `-VVV` option before filing a bug report."
523
+ ui.info "Exception: #{e.class.name}: #{e.message}"
524
+ when Chef::Exceptions::PrivateKeyMissing
525
+ ui.error "Your private key could not be loaded from #{api_key}"
526
+ ui.info "Check your configuration file and ensure that your private key is readable"
527
+ when Chef::Exceptions::InvalidRedirect
528
+ ui.error "Invalid Redirect: #{e.message}"
529
+ ui.info "Change your server location in config.rb/knife.rb to the server's FQDN to avoid unwanted redirections."
530
+ else
531
+ ui.error "#{e.class.name}: #{e.message}"
532
+ end
533
+ end
534
+
535
+ def humanize_http_exception(e)
536
+ response = e.response
537
+ case response
538
+ when Net::HTTPUnauthorized
539
+ ui.error "Failed to authenticate to #{server_url} as #{username} with key #{api_key}"
540
+ ui.info "Response: #{format_rest_error(response)}"
541
+ when Net::HTTPForbidden
542
+ ui.error "You authenticated successfully to #{server_url} as #{username} but you are not authorized for this action."
543
+ proxy_env_vars = ENV.to_hash.keys.map(&:downcase) & %w{http_proxy https_proxy ftp_proxy socks_proxy no_proxy}
544
+ unless proxy_env_vars.empty?
545
+ ui.error "There are proxy servers configured, your server url may need to be added to NO_PROXY."
546
+ end
547
+ ui.info "Response: #{format_rest_error(response)}"
548
+ when Net::HTTPBadRequest
549
+ ui.error "The data in your request was invalid"
550
+ ui.info "Response: #{format_rest_error(response)}"
551
+ when Net::HTTPNotFound
552
+ ui.error "The object you are looking for could not be found"
553
+ ui.info "Response: #{format_rest_error(response)}"
554
+ when Net::HTTPInternalServerError
555
+ ui.error "internal server error"
556
+ ui.info "Response: #{format_rest_error(response)}"
557
+ when Net::HTTPBadGateway
558
+ ui.error "bad gateway"
559
+ ui.info "Response: #{format_rest_error(response)}"
560
+ when Net::HTTPServiceUnavailable
561
+ ui.error "Service temporarily unavailable"
562
+ ui.info "Response: #{format_rest_error(response)}"
563
+ when Net::HTTPNotAcceptable
564
+ version_header = Chef::JSONCompat.from_json(response["x-ops-server-api-version"])
565
+ client_api_version = version_header["request_version"]
566
+ min_server_version = version_header["min_version"]
567
+ max_server_version = version_header["max_version"]
568
+ ui.error "The API version that Knife is using is not supported by the server you sent this request to."
569
+ ui.info "The request that Knife sent was using API version #{client_api_version}."
570
+ 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}."
571
+ ui.info "Please either update your #{ChefUtils::Dist::Infra::PRODUCT} or the server to be a compatible set."
572
+ else
573
+ ui.error response.message
574
+ ui.info "Response: #{format_rest_error(response)}"
575
+ end
576
+ end
577
+
578
+ def username
579
+ Chef::Config[:node_name]
580
+ end
581
+
582
+ def api_key
583
+ Chef::Config[:client_key]
584
+ end
585
+
586
+ # Parses JSON from the error response sent by Chef Server and returns the
587
+ # error message
588
+ #--
589
+ # TODO: this code belongs in Chef::REST
590
+ def format_rest_error(response)
591
+ Array(Chef::JSONCompat.from_json(response.body)["error"]).join("; ")
592
+ rescue Exception
593
+ response.body
594
+ end
595
+
596
+ # FIXME: yard with @yield
597
+ def create_object(object, pretty_name = nil, object_class: nil)
598
+ output = if object_class
599
+ edit_data(object, object_class: object_class)
600
+ else
601
+ edit_hash(object)
602
+ end
603
+
604
+ if Kernel.block_given?
605
+ output = yield(output)
606
+ else
607
+ output.save
608
+ end
609
+
610
+ pretty_name ||= output
611
+
612
+ msg("Created #{pretty_name}")
613
+
614
+ output(output) if config[:print_after]
615
+ end
616
+
617
+ # FIXME: yard with @yield
618
+ def delete_object(klass, name, delete_name = nil)
619
+ confirm("Do you really want to delete #{name}")
620
+
621
+ if Kernel.block_given?
622
+ object = yield
623
+ else
624
+ object = klass.load(name)
625
+ object.destroy
626
+ end
627
+
628
+ output(format_for_display(object)) if config[:print_after]
629
+
630
+ obj_name = delete_name ? "#{delete_name}[#{name}]" : object
631
+ msg("Deleted #{obj_name}")
632
+ end
633
+
634
+ # helper method for testing if a field exists
635
+ # and returning the usage and proper error if not
636
+ def test_mandatory_field(field, fieldname)
637
+ if field.nil?
638
+ show_usage
639
+ ui.fatal("You must specify a #{fieldname}")
640
+ exit 1
641
+ end
642
+ end
643
+
644
+ def rest
645
+ @rest ||= Chef::ServerAPI.new(Chef::Config[:chef_server_url])
646
+ end
647
+
648
+ def noauth_rest
649
+ @rest ||= begin
650
+ require "chef/http/simple_json" unless defined?(Chef::HTTP::SimpleJSON)
651
+ Chef::HTTP::SimpleJSON.new(Chef::Config[:chef_server_url])
652
+ end
653
+ end
654
+
655
+ def server_url
656
+ Chef::Config[:chef_server_url]
657
+ end
658
+
659
+ def maybe_setup_fips
660
+ unless config[:fips].nil?
661
+ Chef::Config[:fips] = config[:fips]
662
+ end
663
+ Chef::Config.init_openssl
664
+ end
665
+
666
+ def root_rest
667
+ @root_rest ||= begin
668
+ require "chef/server_api" unless defined? Chef::ServerAPI
669
+ Chef::ServerAPI.new(Chef::Config[:chef_server_root])
670
+ end
671
+ end
672
+ end
673
+ end