brightbox-cli 3.3.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.gitignore +1 -1
  5. data/.rubocop.yml +70 -0
  6. data/CHANGELOG.md +60 -0
  7. data/Gemfile.lock +74 -45
  8. data/Jenkinsfile +12 -32
  9. data/README +23 -32
  10. data/README.rdoc +1 -1
  11. data/brightbox-cli.gemspec +21 -34
  12. data/lib/brightbox-cli/accounts.rb +9 -11
  13. data/lib/brightbox-cli/api.rb +38 -36
  14. data/lib/brightbox-cli/cloud_ips.rb +8 -8
  15. data/lib/brightbox-cli/collaborating_account.rb +5 -5
  16. data/lib/brightbox-cli/collaboration.rb +1 -1
  17. data/lib/brightbox-cli/commands/accounts/{accept-invite.rb → accept_invite.rb} +2 -6
  18. data/lib/brightbox-cli/commands/accounts/default.rb +1 -2
  19. data/lib/brightbox-cli/commands/accounts/list.rb +6 -8
  20. data/lib/brightbox-cli/commands/accounts/remove.rb +2 -6
  21. data/lib/brightbox-cli/commands/accounts/{reset-ftp-password.rb → reset_ftp_password.rb} +6 -9
  22. data/lib/brightbox-cli/commands/accounts/show.rb +10 -13
  23. data/lib/brightbox-cli/commands/cloudips/create.rb +2 -5
  24. data/lib/brightbox-cli/commands/cloudips/destroy.rb +10 -14
  25. data/lib/brightbox-cli/commands/cloudips/list.rb +0 -2
  26. data/lib/brightbox-cli/commands/cloudips/map.rb +10 -13
  27. data/lib/brightbox-cli/commands/cloudips/show.rb +11 -14
  28. data/lib/brightbox-cli/commands/cloudips/unmap.rb +2 -4
  29. data/lib/brightbox-cli/commands/cloudips/update.rb +2 -4
  30. data/lib/brightbox-cli/commands/collaborations.rb +2 -3
  31. data/lib/brightbox-cli/commands/config/{client-add.rb → client_add.rb} +0 -3
  32. data/lib/brightbox-cli/commands/config/client_default.rb +18 -0
  33. data/lib/brightbox-cli/commands/config/{client-list.rb → client_list.rb} +1 -4
  34. data/lib/brightbox-cli/commands/config/{client-remove.rb → client_remove.rb} +0 -3
  35. data/lib/brightbox-cli/commands/config/{user-add.rb → user_add.rb} +1 -4
  36. data/lib/brightbox-cli/commands/firewall/{policies-apply.rb → policies_apply.rb} +2 -2
  37. data/lib/brightbox-cli/commands/firewall/{policies-create.rb → policies_create.rb} +2 -4
  38. data/lib/brightbox-cli/commands/firewall/{policies-destroy.rb → policies_destroy.rb} +0 -3
  39. data/lib/brightbox-cli/commands/firewall/{policies-list.rb → policies_list.rb} +0 -2
  40. data/lib/brightbox-cli/commands/firewall/{policies-remove.rb → policies_remove.rb} +2 -2
  41. data/lib/brightbox-cli/commands/firewall/{policies-show.rb → policies_show.rb} +6 -8
  42. data/lib/brightbox-cli/commands/firewall/{policies-update.rb → policies_update.rb} +2 -4
  43. data/lib/brightbox-cli/commands/firewall/{rules-create.rb → rules_create.rb} +6 -8
  44. data/lib/brightbox-cli/commands/firewall/{rules-destroy.rb → rules_destroy.rb} +0 -2
  45. data/lib/brightbox-cli/commands/firewall/{rules-list.rb → rules_list.rb} +0 -2
  46. data/lib/brightbox-cli/commands/firewall/{rules-show.rb → rules_show.rb} +7 -9
  47. data/lib/brightbox-cli/commands/firewall/{rules-update.rb → rules_update.rb} +7 -8
  48. data/lib/brightbox-cli/commands/groups/{add-server.rb → add_server.rb} +0 -2
  49. data/lib/brightbox-cli/commands/groups/create.rb +2 -3
  50. data/lib/brightbox-cli/commands/groups/destroy.rb +0 -2
  51. data/lib/brightbox-cli/commands/groups/list.rb +0 -1
  52. data/lib/brightbox-cli/commands/groups/move_servers.rb +2 -3
  53. data/lib/brightbox-cli/commands/groups/{remove-servers.rb → remove_servers.rb} +2 -4
  54. data/lib/brightbox-cli/commands/groups/show.rb +0 -2
  55. data/lib/brightbox-cli/commands/groups/update.rb +2 -3
  56. data/lib/brightbox-cli/commands/images/destroy.rb +0 -4
  57. data/lib/brightbox-cli/commands/images/list.rb +3 -5
  58. data/lib/brightbox-cli/commands/images/register.rb +9 -17
  59. data/lib/brightbox-cli/commands/images/show.rb +19 -20
  60. data/lib/brightbox-cli/commands/images/update.rb +12 -8
  61. data/lib/brightbox-cli/commands/lbs/{add-nodes.rb → add_nodes.rb} +0 -3
  62. data/lib/brightbox-cli/commands/lbs/create.rb +5 -7
  63. data/lib/brightbox-cli/commands/lbs/destroy.rb +0 -3
  64. data/lib/brightbox-cli/commands/lbs/list.rb +0 -1
  65. data/lib/brightbox-cli/commands/lbs/{remove-nodes.rb → remove_nodes.rb} +0 -3
  66. data/lib/brightbox-cli/commands/lbs/show.rb +20 -22
  67. data/lib/brightbox-cli/commands/lbs/update.rb +6 -9
  68. data/lib/brightbox-cli/commands/login.rb +13 -12
  69. data/lib/brightbox-cli/commands/servers/{activate-console.rb → activate_console.rb} +2 -5
  70. data/lib/brightbox-cli/commands/servers/create.rb +32 -26
  71. data/lib/brightbox-cli/commands/servers/destroy.rb +0 -3
  72. data/lib/brightbox-cli/commands/servers/list.rb +4 -5
  73. data/lib/brightbox-cli/commands/servers/show.rb +0 -2
  74. data/lib/brightbox-cli/commands/servers/shutdown.rb +0 -3
  75. data/lib/brightbox-cli/commands/servers/snapshot.rb +0 -4
  76. data/lib/brightbox-cli/commands/servers/start.rb +0 -4
  77. data/lib/brightbox-cli/commands/servers/stop.rb +0 -3
  78. data/lib/brightbox-cli/commands/servers/update.rb +5 -5
  79. data/lib/brightbox-cli/commands/sql/instances_create.rb +3 -6
  80. data/lib/brightbox-cli/commands/sql/instances_destroy.rb +0 -2
  81. data/lib/brightbox-cli/commands/sql/instances_list.rb +7 -9
  82. data/lib/brightbox-cli/commands/sql/instances_reset_password.rb +0 -1
  83. data/lib/brightbox-cli/commands/sql/instances_show.rb +0 -3
  84. data/lib/brightbox-cli/commands/sql/instances_snapshot.rb +0 -3
  85. data/lib/brightbox-cli/commands/sql/instances_update.rb +1 -3
  86. data/lib/brightbox-cli/commands/sql/snapshots_destroy.rb +0 -3
  87. data/lib/brightbox-cli/commands/sql/snapshots_list.rb +7 -9
  88. data/lib/brightbox-cli/commands/sql/snapshots_show.rb +12 -15
  89. data/lib/brightbox-cli/commands/sql/snapshots_update.rb +1 -3
  90. data/lib/brightbox-cli/commands/sql/types.rb +8 -15
  91. data/lib/brightbox-cli/commands/token.rb +0 -1
  92. data/lib/brightbox-cli/commands/types.rb +8 -14
  93. data/lib/brightbox-cli/commands/{user-collaborations.rb → user_collaborations.rb} +7 -8
  94. data/lib/brightbox-cli/commands/users/list.rb +0 -2
  95. data/lib/brightbox-cli/commands/users/show.rb +1 -3
  96. data/lib/brightbox-cli/commands/users/update.rb +3 -6
  97. data/lib/brightbox-cli/commands/zones.rb +7 -10
  98. data/lib/brightbox-cli/config/accounts.rb +18 -26
  99. data/lib/brightbox-cli/config/api_client.rb +12 -16
  100. data/lib/brightbox-cli/config/authentication_tokens.rb +39 -42
  101. data/lib/brightbox-cli/config/cache.rb +1 -0
  102. data/lib/brightbox-cli/config/clients.rb +8 -8
  103. data/lib/brightbox-cli/config/gpg_encrypted_passwords.rb +6 -8
  104. data/lib/brightbox-cli/config/password_helper.rb +33 -8
  105. data/lib/brightbox-cli/config/sections.rb +45 -29
  106. data/lib/brightbox-cli/config/two_factor_auth.rb +12 -14
  107. data/lib/brightbox-cli/config/two_factor_helper.rb +5 -7
  108. data/lib/brightbox-cli/config/user_application.rb +18 -18
  109. data/lib/brightbox-cli/config.rb +26 -23
  110. data/lib/brightbox-cli/connection_manager.rb +4 -2
  111. data/lib/brightbox-cli/database_server.rb +28 -29
  112. data/lib/brightbox-cli/database_snapshot.rb +1 -1
  113. data/lib/brightbox-cli/database_type.rb +6 -6
  114. data/lib/brightbox-cli/detailed_server.rb +43 -43
  115. data/lib/brightbox-cli/detailed_server_group.rb +1 -1
  116. data/lib/brightbox-cli/error_parser.rb +9 -9
  117. data/lib/brightbox-cli/firewall_policy.rb +2 -1
  118. data/lib/brightbox-cli/firewall_rule.rb +3 -3
  119. data/lib/brightbox-cli/firewall_rules.rb +3 -3
  120. data/lib/brightbox-cli/gli_global_hooks.rb +25 -27
  121. data/lib/brightbox-cli/images.rb +14 -12
  122. data/lib/brightbox-cli/load_balancers.rb +3 -6
  123. data/lib/brightbox-cli/logging.rb +14 -14
  124. data/lib/brightbox-cli/nilable_hash.rb +1 -1
  125. data/lib/brightbox-cli/ruby_core_ext.rb +3 -3
  126. data/lib/brightbox-cli/server_groups.rb +2 -2
  127. data/lib/brightbox-cli/servers.rb +6 -6
  128. data/lib/brightbox-cli/tables.rb +13 -15
  129. data/lib/brightbox-cli/types.rb +6 -6
  130. data/lib/brightbox-cli/user_collaboration.rb +5 -7
  131. data/lib/brightbox-cli/users.rb +1 -1
  132. data/lib/brightbox-cli/version.rb +1 -1
  133. data/lib/brightbox-cli/zones.rb +1 -1
  134. data/lib/brightbox_cli.rb +33 -33
  135. data/locales/en.yml +2 -0
  136. data/spec/brightbox_spec.rb +0 -1
  137. data/spec/cassettes/Brightbox_Account/_all/when_connected_using_an_application/returns_a_collection_of_Accounts.yml +5 -5
  138. data/spec/cassettes/Brightbox_Account/_all/when_connected_using_an_application/returns_resources_on_the_same_connection.yml +2 -2
  139. data/spec/cassettes/Brightbox_Account/_all/when_connected_using_an_client/returns_a_collection_of_Accounts.yml +4 -4
  140. data/spec/cassettes/Brightbox_Account/_all/when_connected_using_an_client/returns_resources_on_the_same_connection.yml +2 -2
  141. data/spec/cassettes/Brightbox_BBConfig/_add_section/when_config_exists_and_overwrite_duplicates_is_false/does_not_update_the_config_file.yml +12 -12
  142. data/spec/cassettes/Brightbox_BBConfig/_add_section/when_config_exists_and_overwrite_duplicates_is_true/does_not_update_the_config_file.yml +12 -12
  143. data/spec/cassettes/Brightbox_BBConfig/_add_section/when_first_and_only_client/saves_changes_to_the_config_file.yml +2 -2
  144. data/spec/cassettes/Brightbox_BBConfig/_add_section/when_first_and_only_client/saves_the_default_account.yml +2 -2
  145. data/spec/cassettes/Brightbox_BBConfig/_add_section/when_first_and_only_client/saves_the_new_client_as_the_default.yml +2 -2
  146. data/spec/cassettes/Brightbox_BBConfig/_find_or_set_default_account/when_client_is_not_authenticated/does_not_raise_an_error.yml +8 -8
  147. data/spec/cassettes/Brightbox_BBConfig/_find_or_set_default_account/when_client_may_access_one_account/updates_the_setting.yml +8 -8
  148. data/spec/cassettes/Brightbox_BBConfig/_renew_tokens/when_config_in_use_is_not_the_default/uses_correct_credentials.yml +1 -1
  149. data/spec/cassettes/Brightbox_BBConfig/_renew_tokens/when_using_a_user_app_with_a_cached_refresh_token/caches_the_new_tokens.yml +1 -1
  150. data/spec/cassettes/Brightbox_BBConfig/_renew_tokens/when_using_a_user_app_with_an_expired_refresh_token/caches_the_new_tokens.yml +2 -2
  151. data/spec/cassettes/Brightbox_BBConfig/_renew_tokens/when_using_a_user_app_with_no_tokens/caches_the_new_tokens.yml +1 -1
  152. data/spec/cassettes/Brightbox_BBConfig/_renew_tokens/when_using_a_user_app_with_no_tokens/prompts_user_to_retry_command.yml +1 -1
  153. data/spec/cassettes/Brightbox_BBConfig/_renew_tokens/when_using_an_API_client_with_no_tokens/caches_a_new_access_token.yml +1 -1
  154. data/spec/cassettes/Brightbox_BBConfig_add_login/when_altering_a_custom_option/does_not_alter_the_configuration.yml +6 -6
  155. data/spec/cassettes/Brightbox_BBConfig_add_login/when_altering_a_custom_option/updates_access_token.yml +6 -6
  156. data/spec/cassettes/Brightbox_BBConfig_add_login/when_altering_a_custom_option/updates_refresh_token.yml +6 -6
  157. data/spec/cassettes/Brightbox_BBConfig_add_login/when_configured_with_custom_options/does_not_alter_the_configuration.yml +6 -6
  158. data/spec/cassettes/Brightbox_BBConfig_add_login/when_configured_with_custom_options/updates_access_token.yml +6 -6
  159. data/spec/cassettes/Brightbox_BBConfig_add_login/when_configured_with_custom_options/updates_refresh_token.yml +6 -6
  160. data/spec/cassettes/Brightbox_BBConfig_add_login/when_logged_in_previously/does_not_alter_the_configuration.yml +9 -9
  161. data/spec/cassettes/Brightbox_BBConfig_add_login/when_logged_in_previously/updates_access_token.yml +9 -9
  162. data/spec/cassettes/Brightbox_BBConfig_add_login/when_logged_in_previously/updates_refresh_token.yml +9 -9
  163. data/spec/cassettes/Brightbox_BBConfig_add_login/when_no_config_exists/creates_the_configuration.yml +6 -6
  164. data/spec/cassettes/Brightbox_BBConfig_add_login/when_no_config_exists/refreshed_tokens.yml +6 -6
  165. data/spec/cassettes/Brightbox_BBConfig_add_login/when_using_an_email_and_suffix/creates_the_configuration.yml +6 -6
  166. data/spec/cassettes/Brightbox_BBConfig_add_login/when_using_an_email_and_suffix/refreshed_tokens.yml +6 -6
  167. data/spec/cassettes/Brightbox_CloudIP/_find_all_/when_a_Cloud_IP_exists/returns_a_suitable.yml +15 -15
  168. data/spec/cassettes/Brightbox_FirewallPolicy/_apply_to/should_apply_firewall_policy.yml +14 -14
  169. data/spec/cassettes/Brightbox_FirewallPolicy/_create/should_create_firewall_policy.yml +14 -14
  170. data/spec/cassettes/Brightbox_FirewallPolicy/_destroy/should_destroy_firewall_policy.yml +16 -16
  171. data/spec/cassettes/Brightbox_FirewallPolicy/_find_all_/when_a_policy_exists/should_list_firewall_policy.yml +13 -13
  172. data/spec/cassettes/Brightbox_FirewallPolicy/_find_or_call/when_a_policy_exists/should_show_firewall_policy.yml +11 -11
  173. data/spec/cassettes/Brightbox_FirewallRule/_create/when_policy_exists/creates_the_rule_successfully.yml +14 -14
  174. data/spec/cassettes/Brightbox_FirewallRule/_destroy/when_rule_exists/destroys_a_rule.yml +12 -12
  175. data/spec/cassettes/Brightbox_FirewallRule/_find/when_rule_exists/can_display_the_result.yml +14 -14
  176. data/spec/cassettes/Brightbox_FirewallRule/_from_policy/when_policy_exists_with_a_rule/lists_all_rules.yml +19 -19
  177. data/spec/cassettes/Brightbox_Server/_destroy/when_server_exists/should_work.yml +12 -12
  178. data/spec/cassettes/Brightbox_Server/_find_all_/when_a_server_exists/should_print_server_list.yml +15 -15
  179. data/spec/cassettes/Brightbox_Server/_show/when_server_exists/shows_detailed_attributes_of_a_server.yml +18 -18
  180. data/spec/cassettes/Brightbox_Server/_shutdown/should_work.yml +18 -18
  181. data/spec/cassettes/Brightbox_Server/_start/should_work.yml +24 -24
  182. data/spec/cassettes/Brightbox_Server/_stop/should_work.yml +18 -18
  183. data/spec/cassettes/Brightbox_Server/_update/when_passing_new_group_membership/should_update_with_group.yml +22 -22
  184. data/spec/cassettes/Brightbox_ServerGroup/_find_all_/when_a_group_exists/list_server_groups.yml +13 -13
  185. data/spec/cassettes/Firewall_policies/update/when_the_policy_does_not_exist/prints_error_to_STDERR.yml +3 -3
  186. data/spec/cassettes/brightbox_accounts/list/_when_access_token_expired_/does_not_report_invalid_token_errors.yml +30 -30
  187. data/spec/cassettes/brightbox_accounts/list/_when_both_tokens_expired_/does_not_report_invalid_token_errors.yml +9 -9
  188. data/spec/cassettes/brightbox_accounts/list/_when_invalid_tokens_/does_not_report_invalid_token_errors.yml +9 -9
  189. data/spec/cassettes/brightbox_accounts/list/_when_no_tokens_/does_not_report_invalid_token_errors.yml +27 -27
  190. data/spec/cassettes/brightbox_accounts/list/_when_no_tokens_/reports_they_were_updated.yml +7 -7
  191. data/spec/cassettes/brightbox_accounts/list/_when_no_tokens_and_password_incorrect_/does_not_report_invalid_token_errors.yml +7 -7
  192. data/spec/cassettes/brightbox_accounts/list/_when_no_tokens_and_password_incorrect_/reports_unable_to_authenticate.yml +6 -6
  193. data/spec/cassettes/brightbox_accounts/list/does_not_error.yml +3 -3
  194. data/spec/cassettes/brightbox_cloudips/map/when_destination_is_a_server_ID/passes_the_interface_identifier_to_the_API.yml +12 -12
  195. data/spec/cassettes/brightbox_cloudips/map/when_destination_is_another_value/passes_the_identifier_to_the_API.yml +7 -7
  196. data/spec/cassettes/brightbox_config/client_add/when_adding_a_new_client/does_not_error.yml +7 -7
  197. data/spec/cassettes/brightbox_config/client_add/when_adding_a_new_client/sets_up_the_config.yml +7 -7
  198. data/spec/cassettes/brightbox_config/client_add/when_new_client_is_first_and_only_client/does_not_change_the_default_client.yml +7 -7
  199. data/spec/cassettes/brightbox_config/client_add/when_new_client_is_first_and_only_client/does_not_error.yml +7 -7
  200. data/spec/cassettes/brightbox_config/client_add/when_new_client_is_first_and_only_client/sets_this_as_the_default_client.yml +7 -7
  201. data/spec/cassettes/brightbox_config/client_add/when_new_client_is_first_and_only_client/sets_up_the_config.yml +7 -7
  202. data/spec/cassettes/brightbox_config/user_add/when_NO_config_file_on_disk/sets_up_the_config.yml +5 -5
  203. data/spec/cassettes/brightbox_config/user_add/when_a_default_client_is_already_set/does_not_change_the_default_client.yml +2 -2
  204. data/spec/cassettes/brightbox_config/user_add/when_application_details_in_config/does_not_error.yml +2 -2
  205. data/spec/cassettes/brightbox_config/user_add/when_application_details_in_config/sets_up_the_config.yml +2 -2
  206. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_only_one_active_account/display_an_warning_about_preselected_default.yml +2 -2
  207. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_only_one_active_account/does_not_error.yml +2 -2
  208. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_only_one_active_account/selects_the_active_account_for_the_default.yml +2 -2
  209. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_only_one_active_account/sets_up_the_config.yml +2 -2
  210. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_to_multiple_accounts/display_an_warning_about_preselected_default.yml +2 -2
  211. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_to_multiple_accounts/does_not_error.yml +2 -2
  212. data/spec/cassettes/brightbox_config/user_add/when_application_has_access_to_multiple_accounts/sets_up_the_config.yml +2 -2
  213. data/spec/cassettes/brightbox_config/user_add/when_new_client_is_first_and_only_client/does_not_error.yml +2 -2
  214. data/spec/cassettes/brightbox_config/user_add/when_new_client_is_first_and_only_client/does_not_prompt_to_rerun_the_command.yml +2 -2
  215. data/spec/cassettes/brightbox_config/user_add/when_new_client_is_first_and_only_client/requests_access_tokens.yml +2 -2
  216. data/spec/cassettes/brightbox_config/user_add/when_new_client_is_first_and_only_client/sets_this_as_the_default_client.yml +2 -2
  217. data/spec/cassettes/brightbox_config/user_add/when_new_client_is_first_and_only_client/sets_up_the_config.yml +5 -5
  218. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments/does_not_error.yml +2 -2
  219. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments/does_not_prompt_to_rerun_the_command.yml +2 -2
  220. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments/requests_access_tokens.yml +2 -2
  221. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments/sets_up_the_config.yml +3 -3
  222. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments_and_api_url/does_not_error.yml +2 -2
  223. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments_and_api_url/requests_access_tokens.yml +2 -2
  224. data/spec/cassettes/brightbox_config/user_add/when_passing_in_required_arguments_and_api_url/sets_up_the_config.yml +2 -2
  225. data/spec/cassettes/brightbox_login/when_alternative_client_credentials_are_given/does_not_error.yml +6 -6
  226. data/spec/cassettes/brightbox_login/when_alternative_client_credentials_are_given/does_not_prompt_to_rerun_the_command.yml +6 -6
  227. data/spec/cassettes/brightbox_login/when_alternative_client_credentials_are_given/prompts_for_the_password.yml +6 -6
  228. data/spec/cassettes/brightbox_login/when_alternative_client_credentials_are_given/requests_access_tokens.yml +6 -6
  229. data/spec/cassettes/brightbox_login/when_alternative_client_credentials_are_given/sets_up_the_config.yml +6 -6
  230. data/spec/cassettes/brightbox_login/when_custom_api/auth_URLs_are_given/does_not_error.yml +6 -6
  231. data/spec/cassettes/brightbox_login/when_custom_api/auth_URLs_are_given/does_not_prompt_to_rerun_the_command.yml +6 -6
  232. data/spec/cassettes/brightbox_login/when_custom_api/auth_URLs_are_given/prompts_for_the_password.yml +6 -6
  233. data/spec/cassettes/brightbox_login/when_custom_api/auth_URLs_are_given/requests_access_tokens.yml +6 -6
  234. data/spec/cassettes/brightbox_login/when_custom_api/auth_URLs_are_given/sets_up_the_config.yml +6 -6
  235. data/spec/cassettes/brightbox_login/when_default_account_is_passed/does_not_error.yml +3 -3
  236. data/spec/cassettes/brightbox_login/when_default_account_is_passed/does_not_prompt_to_rerun_the_command.yml +3 -3
  237. data/spec/cassettes/brightbox_login/when_default_account_is_passed/prompts_for_the_password.yml +3 -3
  238. data/spec/cassettes/brightbox_login/when_default_account_is_passed/requests_access_tokens.yml +3 -3
  239. data/spec/cassettes/brightbox_login/when_default_account_is_passed/sets_up_the_config.yml +3 -3
  240. data/spec/cassettes/brightbox_login/when_no_config_is_present/does_not_error.yml +6 -6
  241. data/spec/cassettes/brightbox_login/when_no_config_is_present/does_not_prompt_to_rerun_the_command.yml +6 -6
  242. data/spec/cassettes/brightbox_login/when_no_config_is_present/requests_access_tokens.yml +6 -6
  243. data/spec/cassettes/brightbox_login/when_no_config_is_present/sets_up_the_config.yml +6 -6
  244. data/spec/cassettes/brightbox_login/when_no_password_is_given/does_not_error.yml +6 -6
  245. data/spec/cassettes/brightbox_login/when_no_password_is_given/does_not_prompt_to_rerun_the_command.yml +6 -6
  246. data/spec/cassettes/brightbox_login/when_no_password_is_given/prompts_for_the_password.yml +6 -6
  247. data/spec/cassettes/brightbox_login/when_no_password_is_given/requests_access_tokens.yml +6 -6
  248. data/spec/cassettes/brightbox_login/when_no_password_is_given/sets_up_the_config.yml +6 -6
  249. data/spec/cassettes/brightbox_sql_instances/create/--allow-access_10_0_0_0/correctly_sends_API_parameters.yml +313 -26
  250. data/spec/cassettes/brightbox_sql_instances/create/--allow-access_srv-12345_grp-12345/correctly_sends_API_parameters.yml +1204 -38
  251. data/spec/cassettes/brightbox_sql_instances/create/--engine_mysql/correctly_sends_API_parameters.yml +596 -26
  252. data/spec/cassettes/brightbox_sql_instances/create/--engine_mysql_--engine-version_5_6/correctly_sends_API_parameters.yml +63 -9
  253. data/spec/cassettes/brightbox_sql_instances/create/--engine_mysql_--engine-version_8_0/correctly_sends_API_parameters.yml +393 -0
  254. data/spec/cassettes/brightbox_sql_instances/create/--maintenance-weekday_5_--maintenance_hour_11/correctly_sends_API_parameters.yml +393 -0
  255. data/spec/cassettes/brightbox_sql_instances/create/--maintenance-weekday_thursday/correctly_sends_API_parameters.yml +393 -0
  256. data/spec/cassettes/brightbox_sql_instances/create/--snapshot_dbi-12345/includes_schedule_fields_in_response.yml +1466 -0
  257. data/spec/cassettes/brightbox_sql_instances/create/--snapshots-schedule_0_12_4_/includes_schedule_fields_in_response.yml +342 -0
  258. data/spec/cassettes/brightbox_sql_instances/create/without_arguments/reports_the_new_admin_password.yml +541 -26
  259. data/spec/cassettes/brightbox_sql_instances/create/without_arguments/reports_the_new_admin_username.yml +484 -26
  260. data/spec/cassettes/brightbox_sql_instances/snapshot/when_database_server_active/correctly_sends_API_parameters.yml +4 -4
  261. data/spec/cassettes/brightbox_sql_instances/snapshot/when_database_server_can_not_be_snapshotted/reports_an_error_to_the_user.yml +2 -2
  262. data/spec/cassettes/brightbox_sql_snapshots/list/when_resources_are_available/does_not_output_to_stderr.yml +2 -2
  263. data/spec/cassettes/brightbox_sql_snapshots/list/when_resources_are_available/outputs_table_details_to_stdout.yml +2 -2
  264. data/spec/cassettes/brightbox_sql_snapshots/show/when_resource_exists/does_not_output_to_stderr.yml +2 -2
  265. data/spec/commands/accounts/default_spec.rb +1 -2
  266. data/spec/commands/accounts/list_spec.rb +7 -8
  267. data/spec/commands/accounts/reset_ftp_password_spec.rb +1 -2
  268. data/spec/commands/accounts/show_spec.rb +1 -2
  269. data/spec/commands/cloudips/create_spec.rb +1 -2
  270. data/spec/commands/cloudips/destroy_spec.rb +1 -2
  271. data/spec/commands/cloudips/list_spec.rb +1 -2
  272. data/spec/commands/cloudips/map_spec.rb +2 -3
  273. data/spec/commands/cloudips/show_spec.rb +1 -2
  274. data/spec/commands/cloudips/unmap_spec.rb +1 -2
  275. data/spec/commands/cloudips/update_spec.rb +7 -8
  276. data/spec/commands/config/client_add_spec.rb +2 -3
  277. data/spec/commands/config/client_default_spec.rb +1 -2
  278. data/spec/commands/config/client_list_spec.rb +1 -2
  279. data/spec/commands/config/client_remove_spec.rb +1 -2
  280. data/spec/commands/config/user_add_spec.rb +3 -4
  281. data/spec/commands/firewall_policies/update_spec.rb +3 -3
  282. data/spec/commands/groups/add_server_spec.rb +1 -2
  283. data/spec/commands/groups/create_spec.rb +1 -2
  284. data/spec/commands/groups/destroy_spec.rb +1 -2
  285. data/spec/commands/groups/list_spec.rb +1 -2
  286. data/spec/commands/groups/move_servers_spec.rb +1 -2
  287. data/spec/commands/groups/remove_servers_spec.rb +1 -2
  288. data/spec/commands/groups/show_spec.rb +1 -2
  289. data/spec/commands/groups/update_spec.rb +1 -2
  290. data/spec/commands/images/destroy_spec.rb +1 -2
  291. data/spec/commands/images/list_spec.rb +62 -63
  292. data/spec/commands/images/locking_spec.rb +4 -4
  293. data/spec/commands/images/register_spec.rb +89 -3
  294. data/spec/commands/images/show_spec.rb +56 -4
  295. data/spec/commands/images/update_spec.rb +53 -3
  296. data/spec/commands/lbs/add_nodes_spec.rb +1 -2
  297. data/spec/commands/lbs/create_spec.rb +2 -3
  298. data/spec/commands/lbs/destroy_spec.rb +1 -2
  299. data/spec/commands/lbs/list_spec.rb +1 -2
  300. data/spec/commands/lbs/locking_spec.rb +4 -4
  301. data/spec/commands/lbs/remove_nodes_spec.rb +1 -2
  302. data/spec/commands/lbs/show_spec.rb +1 -2
  303. data/spec/commands/lbs/update_spec.rb +3 -4
  304. data/spec/commands/login_spec.rb +134 -30
  305. data/spec/commands/policies/apply_spec.rb +1 -2
  306. data/spec/commands/policies/create_spec.rb +1 -2
  307. data/spec/commands/policies/destroy_spec.rb +1 -2
  308. data/spec/commands/policies/list_spec.rb +1 -2
  309. data/spec/commands/policies/remove_spec.rb +1 -2
  310. data/spec/commands/policies/show_spec.rb +1 -2
  311. data/spec/commands/policies/update_spec.rb +1 -2
  312. data/spec/commands/rules/create_spec.rb +1 -2
  313. data/spec/commands/rules/destroy_spec.rb +1 -2
  314. data/spec/commands/rules/list_spec.rb +1 -2
  315. data/spec/commands/rules/show_spec.rb +1 -2
  316. data/spec/commands/rules/update_spec.rb +1 -2
  317. data/spec/commands/servers/activate_console_spec.rb +1 -2
  318. data/spec/commands/servers/create_spec.rb +112 -10
  319. data/spec/commands/servers/destroy_spec.rb +1 -2
  320. data/spec/commands/servers/list_spec.rb +1 -2
  321. data/spec/commands/servers/locking_spec.rb +4 -4
  322. data/spec/commands/servers/reboot_spec.rb +3 -4
  323. data/spec/commands/servers/reset_spec.rb +3 -4
  324. data/spec/commands/servers/show_spec.rb +1 -2
  325. data/spec/commands/servers/shutdown_spec.rb +1 -2
  326. data/spec/commands/servers/snapshot_spec.rb +1 -2
  327. data/spec/commands/servers/start_spec.rb +1 -2
  328. data/spec/commands/servers/stop_spec.rb +1 -2
  329. data/spec/commands/servers/update_spec.rb +1 -2
  330. data/spec/commands/sql/instances/create_spec.rb +58 -75
  331. data/spec/commands/sql/instances/locking_spec.rb +4 -4
  332. data/spec/commands/sql/instances/show_spec.rb +7 -7
  333. data/spec/commands/sql/instances/snapshot_spec.rb +2 -2
  334. data/spec/commands/sql/instances/update_spec.rb +8 -8
  335. data/spec/commands/sql/snapshots/list_spec.rb +1 -1
  336. data/spec/commands/sql/snapshots/locking_spec.rb +4 -4
  337. data/spec/commands/sql/snapshots/show_spec.rb +1 -1
  338. data/spec/commands/sql/types/list_spec.rb +1 -2
  339. data/spec/commands/types/list_spec.rb +1 -2
  340. data/spec/commands/users/list_spec.rb +1 -2
  341. data/spec/commands/users/show_spec.rb +1 -2
  342. data/spec/commands/users/update_spec.rb +1 -2
  343. data/spec/commands/zones/list_spec.rb +1 -2
  344. data/spec/configs/api_client.ini +1 -1
  345. data/spec/configs/user_app.ini +2 -2
  346. data/spec/spec_helper.rb +16 -3
  347. data/spec/support/authentication_helpers.rb +98 -0
  348. data/spec/support/config_helpers.rb +2 -4
  349. data/spec/support/password_prompt_helpers.rb +22 -1
  350. data/spec/support/server_helper.rb +5 -5
  351. data/spec/support/tmp_config.rb +1 -1
  352. data/spec/support/token_helpers.rb +2 -2
  353. data/spec/support/vcr.rb +3 -22
  354. data/spec/unit/brightbox/api/created_on_spec.rb +2 -2
  355. data/spec/unit/brightbox/api/fog_model_spec.rb +13 -13
  356. data/spec/unit/brightbox/api/klass_name_spec.rb +0 -1
  357. data/spec/unit/brightbox/api/method_missing_spec.rb +64 -0
  358. data/spec/unit/brightbox/api/require_account_spec.rb +0 -1
  359. data/spec/unit/brightbox/api/respond_to_spec.rb +71 -0
  360. data/spec/unit/brightbox/bb_config/access_token_filename_spec.rb +0 -1
  361. data/spec/unit/brightbox/bb_config/account_spec.rb +0 -1
  362. data/spec/unit/brightbox/bb_config/add_login_spec.rb +27 -28
  363. data/spec/unit/brightbox/bb_config/add_section_spec.rb +1 -2
  364. data/spec/unit/brightbox/bb_config/clear_default_client_spec.rb +0 -1
  365. data/spec/unit/brightbox/bb_config/client_id_spec.rb +0 -1
  366. data/spec/unit/brightbox/bb_config/client_name_spec.rb +0 -1
  367. data/spec/unit/brightbox/bb_config/config_directory_exists_spec.rb +0 -1
  368. data/spec/unit/brightbox/bb_config/config_directory_spec.rb +0 -1
  369. data/spec/unit/brightbox/bb_config/config_spec.rb +2 -3
  370. data/spec/unit/brightbox/bb_config/default_account_spec.rb +0 -1
  371. data/spec/unit/brightbox/bb_config/default_client_spec.rb +0 -1
  372. data/spec/unit/brightbox/bb_config/delete_section_spec.rb +0 -1
  373. data/spec/unit/brightbox/bb_config/find_or_set_default_account_spec.rb +4 -4
  374. data/spec/unit/brightbox/bb_config/refresh_token_filename_spec.rb +0 -1
  375. data/spec/unit/brightbox/bb_config/renew_tokens_spec.rb +3 -4
  376. data/spec/unit/brightbox/bb_config/save_default_account_spec.rb +0 -1
  377. data/spec/unit/brightbox/bb_config/save_spec.rb +0 -1
  378. data/spec/unit/brightbox/bb_config/section_names_spec.rb +1 -1
  379. data/spec/unit/brightbox/bb_config/to_fog_spec.rb +2 -2
  380. data/spec/unit/brightbox/collaborating_account/to_row_spec.rb +3 -3
  381. data/spec/unit/brightbox/config/api_client/to_fog_spec.rb +8 -8
  382. data/spec/unit/brightbox/config/api_client/valid_spec.rb +4 -4
  383. data/spec/unit/brightbox/config/discover_two_factor_pin_spec.rb +87 -0
  384. data/spec/unit/brightbox/config/section_name_deduplicator_spec.rb +1 -1
  385. data/spec/unit/brightbox/config/user_application/to_fog_spec.rb +10 -10
  386. data/spec/unit/brightbox/config/user_application/valid_spec.rb +3 -3
  387. data/spec/unit/brightbox/connection_manager/fetch_connection_spec.rb +1 -1
  388. data/spec/unit/brightbox/database_server/clean_arguments_spec.rb +1 -2
  389. data/spec/unit/brightbox/database_server/maintenance_window_spec.rb +0 -1
  390. data/spec/unit/brightbox/error_parser/pretty_print_spec.rb +0 -1
  391. data/spec/unit/brightbox/firewall_policy/apply_to_spec.rb +0 -1
  392. data/spec/unit/brightbox/firewall_policy/create_spec.rb +0 -1
  393. data/spec/unit/brightbox/firewall_policy/find_or_call_spec.rb +0 -1
  394. data/spec/unit/brightbox/firewall_policy/find_spec.rb +0 -1
  395. data/spec/unit/brightbox/firewall_rule/find_spec.rb +9 -9
  396. data/spec/unit/brightbox/firewall_rule/from_policy_spec.rb +4 -4
  397. data/spec/unit/brightbox/legacy/args_adjuster_spec.rb +20 -21
  398. data/spec/unit/brightbox/server/create_spec.rb +1 -2
  399. data/spec/unit/brightbox/server/start_spec.rb +2 -2
  400. data/spec/unit/brightbox/server/update_spec.rb +0 -1
  401. data/spec/unit/brightbox/user_collaboration/remove_spec.rb +0 -1
  402. data/spec/unit/nilable_hash_spec.rb +5 -5
  403. data/spec/unit/ruby_core_ext_spec.rb +3 -4
  404. data/spec/unit/temporary_home_spec.rb +1 -1
  405. data/spec/unit/tmp_config_spec.rb +0 -1
  406. metadata +131 -99
  407. data/bin/brightbox-accounts +0 -13
  408. data/bin/brightbox-cloudips +0 -13
  409. data/bin/brightbox-config +0 -13
  410. data/bin/brightbox-firewall-policies +0 -13
  411. data/bin/brightbox-firewall-rules +0 -13
  412. data/bin/brightbox-groups +0 -13
  413. data/bin/brightbox-images +0 -13
  414. data/bin/brightbox-lbs +0 -13
  415. data/bin/brightbox-servers +0 -13
  416. data/bin/brightbox-types +0 -13
  417. data/bin/brightbox-users +0 -13
  418. data/bin/brightbox-zones +0 -13
  419. data/lib/brightbox-cli/commands/config/client-default.rb +0 -26
@@ -12,11 +12,10 @@ module Brightbox
12
12
  if defined?(@access_token) && !@access_token.nil?
13
13
  return @access_token
14
14
  end
15
- if File.exist?(access_token_filename)
16
- @access_token = cached_access_token
17
- else
18
- @access_token = nil
19
- end
15
+
16
+ @access_token = if File.exist?(access_token_filename)
17
+ cached_access_token
18
+ end
20
19
  end
21
20
 
22
21
  def refresh_token_filename
@@ -28,11 +27,10 @@ module Brightbox
28
27
  if defined?(@refresh_token) && !@refresh_token.nil?
29
28
  return @refresh_token
30
29
  end
31
- if File.exist?(refresh_token_filename)
32
- @refresh_token = cached_refresh_token
33
- else
34
- @refresh_token = nil
35
- end
30
+
31
+ @refresh_token = if File.exist?(refresh_token_filename)
32
+ cached_refresh_token
33
+ end
36
34
  end
37
35
 
38
36
  # @deprecation use access_token instead
@@ -70,6 +68,7 @@ module Brightbox
70
68
  # through the process.
71
69
  #
72
70
  password = options[:password] if options[:password]
71
+ one_time_password = options[:one_time_password] if options[:one_time_password]
73
72
 
74
73
  # To prevent refreshing tokens for the wrong client (using client_name
75
74
  # is pretty random) we set it specially
@@ -82,11 +81,15 @@ module Brightbox
82
81
  if refresh_token
83
82
  begin
84
83
  service = update_tokens_with_refresh_token
85
- rescue Excon::Errors::BadRequest, Excon::Errors::Unauthorized
84
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError, Excon::Errors::BadRequest, Excon::Errors::Unauthorized
86
85
  service = update_tokens_with_user_credentials
87
86
  end
88
87
  else
89
- service = update_tokens_with_user_credentials(password)
88
+ begin
89
+ service = update_tokens_with_user_credentials(password: password, one_time_password: one_time_password)
90
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError, Excon::Errors::BadRequest, Excon::Errors::Unauthorized
91
+ service = update_tokens_with_user_credentials(password: password)
92
+ end
90
93
  end
91
94
  else
92
95
  service = update_tokens_with_client_credentials
@@ -95,7 +98,6 @@ module Brightbox
95
98
  new_access_token = service.access_token
96
99
  new_refresh_token = service.refresh_token
97
100
  update_stored_tokens(new_access_token, new_refresh_token)
98
-
99
101
  rescue Excon::Errors::BadRequest, Excon::Errors::Unauthorized
100
102
  error "ERROR: Unable to reauthenticate!"
101
103
  ensure
@@ -115,7 +117,9 @@ module Brightbox
115
117
  # authenticate with the API.
116
118
  #
117
119
  def save_access_token(current_access_token)
118
- if access_token != current_access_token
120
+ if access_token == current_access_token
121
+ debug "Access token remains #{access_token}"
122
+ else
119
123
  @access_token = current_access_token
120
124
  debug "Attempting to save new access token: #{current_access_token}"
121
125
  debug "In memory access token: #{@access_token}"
@@ -124,8 +128,6 @@ module Brightbox
124
128
  persist_token(access_token_filename, current_access_token)
125
129
 
126
130
  current_access_token
127
- else
128
- debug "Access token remains #{access_token}"
129
131
  end
130
132
  end
131
133
 
@@ -133,7 +135,9 @@ module Brightbox
133
135
  # request a new access token when current one has expired.
134
136
  #
135
137
  def save_refresh_token(current_token)
136
- if refresh_token != current_token
138
+ if refresh_token == current_token
139
+ debug "Refresh token remains #{refresh_token}"
140
+ else
137
141
  @refresh_token = current_token
138
142
  debug "Attempting to save new refresh token: #{current_token}"
139
143
  debug "In memory refresh token: #{@refresh_token}"
@@ -142,8 +146,6 @@ module Brightbox
142
146
  persist_token(refresh_token_filename, current_token)
143
147
 
144
148
  current_token
145
- else
146
- debug "Refresh token remains #{refresh_token}"
147
149
  end
148
150
  end
149
151
 
@@ -177,32 +179,30 @@ module Brightbox
177
179
  connection
178
180
  end
179
181
 
180
- # This asks the user to input their password
181
- def prompt_for_password
182
- require "highline"
183
- highline = HighLine.new
184
- highline.say("Your API credentials have expired, enter your password to update them.")
185
- # FIXME: Capture interupts if user aborts
186
- highline.ask("Enter your password : ") { |q| q.echo = false }
187
- end
188
-
189
- def update_tokens_with_user_credentials(password = nil)
182
+ def update_tokens_with_user_credentials(password: nil, one_time_password: nil)
190
183
  user_application = Brightbox::Config::UserApplication.new(selected_config, client_name)
191
184
 
192
- password ||= gpg_password
193
- password ||= password_helper_password
194
- password ||= prompt_for_password
195
-
196
- password = extend_with_two_factor_pin(password)
185
+ password = discover_password(password: password, expired: true)
197
186
 
198
187
  # FIXME: options are required to work
199
188
  options = {
200
189
  :client_id => client_name,
201
190
  :email => selected_config["username"],
202
- :password => password
191
+ :password => password,
192
+ :one_time_password => one_time_password
203
193
  }
204
194
 
205
- user_application.fetch_refresh_token(options)
195
+ begin
196
+ user_application.fetch_refresh_token(options)
197
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError
198
+ options = {
199
+ :client_id => client_name,
200
+ :email => selected_config["username"],
201
+ :password => password,
202
+ :one_time_password => discover_two_factor_pin
203
+ }
204
+ user_application.fetch_refresh_token(options)
205
+ end
206
206
  end
207
207
 
208
208
  def fetch_refresh_token(options)
@@ -210,7 +210,7 @@ module Brightbox
210
210
  client_config = config[client_name]
211
211
  user_application = Brightbox::Config::UserApplication.new(client_config, client_name)
212
212
  # replace this portion with code that actually fetches a token
213
- client_config['refresh_token'] = user_application.fetch_refresh_token(options)
213
+ client_config["refresh_token"] = user_application.fetch_refresh_token(options)
214
214
  save_refresh_token
215
215
  end
216
216
 
@@ -223,9 +223,7 @@ module Brightbox
223
223
  def persist_token(filename, token)
224
224
  token = "" if token.nil?
225
225
  # Write out a token file for this process
226
- File.open(filename + ".#{$PID}", "w") do |f|
227
- f.write token
228
- end
226
+ File.write(filename + ".#{$PID}", token)
229
227
  # Move process version into place
230
228
  debug "Saving #{token} to #{filename}"
231
229
  FileUtils.mv filename + ".#{$PID}", filename
@@ -258,10 +256,9 @@ module Brightbox
258
256
  FileUtils.rm(refresh_token_filename) if File.exist?(refresh_token_filename)
259
257
  end
260
258
 
261
- private
262
-
263
259
  def base_token_name
264
260
  return nil if client_name.nil?
261
+
265
262
  client_name.gsub("/", "_")
266
263
  end
267
264
  end
@@ -7,6 +7,7 @@ module Brightbox
7
7
 
8
8
  def cache_id(cid)
9
9
  return if cid.nil?
10
+
10
11
  unless File.exist?(cache_path)
11
12
  begin
12
13
  FileUtils.mkpath(cache_path)
@@ -8,11 +8,9 @@ module Brightbox
8
8
 
9
9
  # Is the currently selected config using user application details?
10
10
  def using_application?
11
- if client_name
12
- !config[client_name]["username"].nil?
13
- else
14
- raise NoSelectedClientError, NO_CLIENT_MESSAGE
15
- end
11
+ raise NoSelectedClientError, NO_CLIENT_MESSAGE unless client_name
12
+
13
+ !config[client_name]["username"].nil?
16
14
  end
17
15
 
18
16
  # Does this config have multiple clients defined within?
@@ -31,6 +29,7 @@ module Brightbox
31
29
  #
32
30
  def client_alias
33
31
  return nil if selected_config.nil?
32
+
34
33
  # FIXME: The 'alias' field is redundant because we are using the section
35
34
  # heading for the not ID value but we worry about it for now
36
35
  selected_config["alias"] || client_name
@@ -61,7 +60,7 @@ module Brightbox
61
60
  #
62
61
  def default_client
63
62
  @default_client ||= core_setting("default_client")
64
- rescue
63
+ rescue StandardError
65
64
  nil
66
65
  end
67
66
 
@@ -76,6 +75,7 @@ module Brightbox
76
75
  def determine_client(preferred_client = nil)
77
76
  return preferred_client unless preferred_client.nil?
78
77
  return default_client unless default_client.nil?
78
+
79
79
  section_names.first unless section_names.empty?
80
80
  nil
81
81
  end
@@ -85,8 +85,8 @@ module Brightbox
85
85
  # If the prefix is in the client ID (identifier not alias) be +true+
86
86
  def config_identifier_match_prefix?(prefix)
87
87
  client_id = selected_config["client_id"]
88
- !! /\A#{prefix}-.*/.match(client_id)
89
- rescue
88
+ !!/\A#{prefix}-.*/.match(client_id)
89
+ rescue StandardError
90
90
  raise NoSelectedClientError, NO_CLIENT_MESSAGE
91
91
  end
92
92
  end
@@ -1,7 +1,7 @@
1
1
  module Brightbox
2
2
  module Config
3
3
  module GpgEncryptedPasswords
4
- attr_accessor :gpg_password
4
+ attr_writer :gpg_password
5
5
 
6
6
  def gpg_encrypted_password_filename
7
7
  file_name = "#{client_name}.password.gpg"
@@ -13,11 +13,10 @@ module Brightbox
13
13
  if defined?(@gpg_password) && !@gpg_password.nil?
14
14
  return @gpg_password
15
15
  end
16
- if File.exist?(gpg_encrypted_password_filename)
17
- @gpg_password = gpg_decrypt_password
18
- else
19
- @gpg_password = nil
20
- end
16
+
17
+ @gpg_password = if File.exist?(gpg_encrypted_password_filename)
18
+ gpg_decrypt_password
19
+ end
21
20
  end
22
21
 
23
22
  private
@@ -26,14 +25,13 @@ module Brightbox
26
25
  def gpg_decrypt_password
27
26
  info "INFO: Decrypting #{gpg_encrypted_password_filename} to obtain password"
28
27
  begin
29
- IO::popen(["gpg", "--decrypt", gpg_encrypted_password_filename], "r") do |io|
28
+ IO.popen(["gpg", "--decrypt", gpg_encrypted_password_filename], "r") do |io|
30
29
  io.read.chomp
31
30
  end
32
31
  rescue Errno::ENOENT
33
32
  nil
34
33
  end
35
34
  end
36
-
37
35
  end
38
36
  end
39
37
  end
@@ -1,7 +1,26 @@
1
1
  module Brightbox
2
2
  module Config
3
3
  module PasswordHelper
4
- attr_accessor :password_helper_password
4
+ ENTER_PASSWORD_PROMPT = "Enter your password : ".freeze
5
+ EXPIRED_TOKEN_PROMPT = "Your API credentials have expired, enter your password to update them.".freeze
6
+
7
+ attr_writer :password_helper_password
8
+
9
+ # {discover_password} will return the first password that can be
10
+ # recovered from either the passed input, encrypted storage, a
11
+ # helper application (if configured) or finally promping.
12
+ #
13
+ # @param password [String] a password given to the method
14
+ # @param expired [Boolean] should the prompt explain tokens have expired?
15
+ # @return [String] the password
16
+ #
17
+ def discover_password(password: nil, expired: false)
18
+ password ||= gpg_password
19
+ password ||= password_helper_password
20
+ password ||= prompt_for_password(expired)
21
+ end
22
+
23
+ private
5
24
 
6
25
  def password_helper_command
7
26
  return config[client_name]["password_helper_command"] unless client_name.nil?
@@ -13,15 +32,11 @@ module Brightbox
13
32
  return @password_helper_password
14
33
  end
15
34
 
16
- if password_helper_command
17
- @password_helper_password = password_helper_call
18
- else
19
- @password_helper_password = nil
20
- end
35
+ @password_helper_password = if password_helper_command
36
+ password_helper_call
37
+ end
21
38
  end
22
39
 
23
- private
24
-
25
40
  def password_helper_call
26
41
  info "INFO: Calling password helper to obtain password"
27
42
  begin
@@ -33,6 +48,16 @@ module Brightbox
33
48
  nil
34
49
  end
35
50
  end
51
+
52
+ # This asks the user to input their password
53
+ def prompt_for_password(expired)
54
+ require "highline"
55
+ highline = HighLine.new
56
+ highline.say(EXPIRED_TOKEN_PROMPT) if expired
57
+
58
+ # FIXME: Capture interupts if user aborts
59
+ highline.ask(ENTER_PASSWORD_PROMPT) { |q| q.echo = false }
60
+ end
36
61
  end
37
62
  end
38
63
  end
@@ -43,18 +43,27 @@ module Brightbox
43
43
  #
44
44
  begin
45
45
  remove_cached_tokens!
46
- renew_tokens(:client_name => config_alias, :password => password)
47
- rescue => e
48
- error "Something went wrong trying to refresh new tokens #{e.message}"
49
- end
46
+ begin
47
+ renew_tokens(client_name: config_alias,
48
+ password: password)
49
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError
50
+ discover_two_factor_pin
51
+
52
+ renew_tokens(client_name: client_alias,
53
+ password: options[:password],
54
+ one_time_password: current_second_factor)
55
+ end
50
56
 
51
- # Try to determine a default account
52
- unless default_account == find_or_set_default_account
53
- info "The default account of #{default_account} has been selected"
54
- end
57
+ # Try to determine a default account
58
+ unless default_account == find_or_set_default_account
59
+ info "The default account of #{default_account} has been selected"
60
+ end
55
61
 
56
- # If only client then set it as the default
57
- set_default_client(client_alias) unless default_client
62
+ # If only client then set it as the default
63
+ set_default_client(client_alias) unless default_client
64
+ rescue StandardError => e
65
+ error "Something went wrong trying to refresh new tokens #{e.message}"
66
+ end
58
67
 
59
68
  # Ensure all our config changes are now saved
60
69
  save
@@ -98,18 +107,25 @@ module Brightbox
98
107
 
99
108
  # Renew tokens via config...
100
109
  begin
101
- renew_tokens(:client_name => client_alias, :password => options[:password])
102
- rescue => e
103
- error "Something went wrong trying to refresh new tokens #{e.message}"
104
- end
110
+ begin
111
+ renew_tokens(client_name: client_alias,
112
+ password: options[:password])
113
+ rescue Fog::Brightbox::OAuth2::TwoFactorMissingError
114
+ renew_tokens(client_name: client_alias,
115
+ password: options[:password],
116
+ one_time_password: discover_two_factor_pin)
117
+ end
105
118
 
106
- # Try to determine a default account
107
- unless default_account == find_or_set_default_account
108
- info "The default account of #{default_account} has been selected"
109
- end
119
+ # Try to determine a default account
120
+ unless default_account == find_or_set_default_account
121
+ info "The default account of #{default_account} has been selected"
122
+ end
110
123
 
111
- # If only client then set it as the default
112
- set_default_client(client_alias) unless default_client
124
+ # If only client then set it as the default
125
+ set_default_client(client_alias) unless default_client
126
+ rescue StandardError => e
127
+ error "Something went wrong trying to refresh new tokens #{e.message}"
128
+ end
113
129
 
114
130
  # Ensure all our config changes are now saved
115
131
  save
@@ -119,16 +135,16 @@ module Brightbox
119
135
  # persisted to disk.
120
136
  #
121
137
  def delete_section(name)
122
- if client_named?(name)
123
- if default_client == name
124
- clear_default_client
125
- end
126
- # remove from the Ini object
127
- config.delete_section(name)
138
+ return unless client_named?(name)
128
139
 
129
- dirty! # to ensure save actually writes to disk
130
- save
140
+ if default_client == name
141
+ clear_default_client
131
142
  end
143
+ # remove from the Ini object
144
+ config.delete_section(name)
145
+
146
+ dirty! # to ensure save actually writes to disk
147
+ save
132
148
  end
133
149
 
134
150
  # Config data for a named section
@@ -150,7 +166,7 @@ module Brightbox
150
166
  #
151
167
  def section_names
152
168
  # Exclude the global "core" section
153
- config.sections.reject { |s| %w(core alias).include?(s) }
169
+ config.sections.reject { |s| %w[core alias].include?(s) }
154
170
  end
155
171
 
156
172
  private
@@ -1,33 +1,31 @@
1
1
  module Brightbox
2
2
  module Config
3
3
  module TwoFactorAuth
4
+ ENTER_TWO_FACTOR_PROMPT = "Enter your two factor pin : ".freeze
4
5
 
5
- def extend_with_two_factor_pin(password)
6
- if two_factor_enabled
7
- suffix = "+" + two_factor_pin
8
- password += suffix unless password.end_with?(suffix)
9
- end
10
- password
6
+ attr_accessor :current_second_factor
7
+
8
+ def discover_two_factor_pin
9
+ @two_factor_pin ||= Brightbox.config.two_factor_helper_password
10
+ @two_factor_pin ||= prompt_for_two_factor_pin
11
+
12
+ self.current_second_factor = @two_factor_pin
11
13
  end
12
14
 
13
15
  private
14
16
 
15
17
  def two_factor_enabled
16
- return config[client_name]["two_factor"] == "true" unless client_name.nil?
17
- end
18
+ return false unless client_name.nil?
19
+ return true if config[client_name]["two_factor"] == "true"
18
20
 
19
- def two_factor_pin
20
- if two_factor_enabled
21
- @two_factor_pin ||= Brightbox.config.two_factor_helper_password
22
- @two_factor_pin ||= prompt_for_two_factor_pin
23
- end
21
+ false
24
22
  end
25
23
 
26
24
  def prompt_for_two_factor_pin
27
25
  require "highline"
28
26
  highline = HighLine.new
29
27
  # FIXME: Capture interupts if user aborts
30
- highline.ask("Enter your two factor pin : ")
28
+ highline.ask(ENTER_TWO_FACTOR_PROMPT)
31
29
  end
32
30
  end
33
31
  end
@@ -1,7 +1,7 @@
1
1
  module Brightbox
2
2
  module Config
3
3
  module TwoFactorHelper
4
- attr_accessor :two_factor_helper_password
4
+ attr_writer :two_factor_helper_password
5
5
 
6
6
  def two_factor_helper_command
7
7
  return config[client_name]["two_factor_helper_command"] unless client_name.nil?
@@ -13,11 +13,9 @@ module Brightbox
13
13
  return @two_factor_helper_password
14
14
  end
15
15
 
16
- if two_factor_helper_command
17
- @two_factor_helper_password = two_factor_helper_call
18
- else
19
- @two_factor_helper_password = nil
20
- end
16
+ @two_factor_helper_password = if two_factor_helper_command
17
+ two_factor_helper_call
18
+ end
21
19
  end
22
20
 
23
21
  private
@@ -29,7 +27,7 @@ module Brightbox
29
27
  IO.popen(cmd, "r") do |io|
30
28
  io.readline.chomp
31
29
  end
32
- rescue Errno::ENOENT
30
+ rescue ArgumentError, Errno::ENOENT
33
31
  nil
34
32
  end
35
33
  end
@@ -3,7 +3,7 @@ module Brightbox
3
3
  class UserApplication
4
4
  # FIXME: api_url should use fog's underlying default
5
5
  #
6
- NON_BLANK_KEYS = %w(api_url username)
6
+ NON_BLANK_KEYS = %w[api_url username].freeze
7
7
 
8
8
  attr_accessor :selected_config, :client_name
9
9
 
@@ -16,11 +16,12 @@ module Brightbox
16
16
  check_required_params
17
17
  # Note we have to merge in refresh token at the higher level
18
18
  {
19
- :provider => 'Brightbox',
20
- :brightbox_api_url => selected_config['api_url'],
21
- :brightbox_auth_url => selected_config['auth_url'] || selected_config['api_url'],
19
+ :provider => "Brightbox",
20
+ :brightbox_api_url => selected_config["api_url"],
21
+ :brightbox_auth_url => selected_config["auth_url"] || selected_config["api_url"],
22
22
  :brightbox_client_id => client_id,
23
23
  :brightbox_secret => client_secret,
24
+ :brightbox_support_two_factor => true,
24
25
  :persistent => persistent?
25
26
  }
26
27
  end
@@ -40,7 +41,9 @@ module Brightbox
40
41
  #
41
42
  def fetch_refresh_token(options)
42
43
  password_options = {
43
- :brightbox_password => options[:password]
44
+ :brightbox_password => options[:password],
45
+ :brightbox_support_two_factor => true,
46
+ :brightbox_one_time_password => options[:one_time_password]
44
47
  }
45
48
 
46
49
  default_fog_options = password_auth_params.merge(password_options)
@@ -64,31 +67,28 @@ module Brightbox
64
67
  end
65
68
 
66
69
  def persistent?
67
- if selected_config["persistent"] == "false"
68
- false
69
- else
70
- true
71
- end
70
+ selected_config["persistent"] != "false"
72
71
  end
73
72
 
74
73
  def password_auth_params
75
74
  {
76
- :provider => 'Brightbox',
77
- :brightbox_api_url => selected_config['api_url'],
78
- :brightbox_auth_url => selected_config['auth_url'] || selected_config['api_url'],
75
+ :provider => "Brightbox",
76
+ :brightbox_api_url => selected_config["api_url"],
77
+ :brightbox_auth_url => selected_config["auth_url"] || selected_config["api_url"],
79
78
  :brightbox_client_id => client_id,
80
79
  :brightbox_secret => client_secret,
81
80
  :brightbox_username => selected_config["username"],
81
+ :brightbox_support_two_factor => true,
82
82
  :persistent => persistent?
83
83
  }
84
84
  end
85
85
 
86
86
  def check_required_params
87
- unless valid?
88
- NON_BLANK_KEYS.each do |key|
89
- unless selected_config.key?(key) && !selected_config[key].to_s.empty?
90
- raise Brightbox::BBConfigError, "#{key} option missing from config in section #{client_name}"
91
- end
87
+ return if valid?
88
+
89
+ NON_BLANK_KEYS.each do |key|
90
+ unless selected_config.key?(key) && !selected_config[key].to_s.empty?
91
+ raise Brightbox::BBConfigError, "#{key} option missing from config in section #{client_name}"
92
92
  end
93
93
  end
94
94
  end