knife 18.0.185 → 18.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (667) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +29 -29
  3. data/LICENSE +201 -201
  4. data/Rakefile +33 -33
  5. data/bin/knife +24 -24
  6. data/knife.gemspec +60 -60
  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 +232 -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 -84
  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 -86
  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 +2233 -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 +3 -3
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