morpheus-cli 3.6.8 → 3.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/account_groups_interface.rb +2 -2
  3. data/lib/morpheus/api/accounts_interface.rb +4 -7
  4. data/lib/morpheus/api/api_client.rb +207 -70
  5. data/lib/morpheus/api/app_templates_interface.rb +7 -28
  6. data/lib/morpheus/api/apps_interface.rb +14 -21
  7. data/lib/morpheus/api/archive_buckets_interface.rb +2 -2
  8. data/lib/morpheus/api/archive_files_interface.rb +6 -6
  9. data/lib/morpheus/api/auth_interface.rb +14 -1
  10. data/lib/morpheus/api/blueprints_interface.rb +9 -16
  11. data/lib/morpheus/api/cloud_datastores_interface.rb +1 -1
  12. data/lib/morpheus/api/cloud_policies_interface.rb +1 -1
  13. data/lib/morpheus/api/clouds_interface.rb +18 -21
  14. data/lib/morpheus/api/cypher_interface.rb +19 -28
  15. data/lib/morpheus/api/file_copy_request_interface.rb +1 -1
  16. data/lib/morpheus/api/group_policies_interface.rb +1 -1
  17. data/lib/morpheus/api/groups_interface.rb +4 -4
  18. data/lib/morpheus/api/image_builder_boot_scripts_interface.rb +1 -1
  19. data/lib/morpheus/api/image_builder_image_builds_interface.rb +2 -2
  20. data/lib/morpheus/api/image_builder_preseed_scripts_interface.rb +1 -1
  21. data/lib/morpheus/api/instances_interface.rb +17 -23
  22. data/lib/morpheus/api/logs_interface.rb +7 -10
  23. data/lib/morpheus/api/network_domains_interface.rb +1 -1
  24. data/lib/morpheus/api/network_groups_interface.rb +1 -1
  25. data/lib/morpheus/api/network_pool_servers_interface.rb +1 -1
  26. data/lib/morpheus/api/network_pools_interface.rb +1 -1
  27. data/lib/morpheus/api/network_proxies_interface.rb +1 -1
  28. data/lib/morpheus/api/network_services_interface.rb +1 -1
  29. data/lib/morpheus/api/networks_interface.rb +1 -1
  30. data/lib/morpheus/api/old_cypher_interface.rb +55 -0
  31. data/lib/morpheus/api/packages_interface.rb +1 -1
  32. data/lib/morpheus/api/policies_interface.rb +1 -1
  33. data/lib/morpheus/api/setup_interface.rb +1 -1
  34. data/lib/morpheus/api/storage_providers_interface.rb +1 -1
  35. data/lib/morpheus/api/whoami_interface.rb +1 -1
  36. data/lib/morpheus/benchmarking.rb +277 -0
  37. data/lib/morpheus/cli.rb +6 -22
  38. data/lib/morpheus/cli/access_token_command.rb +172 -0
  39. data/lib/morpheus/cli/accounts.rb +5 -0
  40. data/lib/morpheus/cli/apps.rb +93 -37
  41. data/lib/morpheus/cli/archives_command.rb +0 -2
  42. data/lib/morpheus/cli/auth_command.rb +112 -0
  43. data/lib/morpheus/cli/blueprints_command.rb +50 -13
  44. data/lib/morpheus/cli/change_password_command.rb +148 -0
  45. data/lib/morpheus/cli/cli_command.rb +173 -49
  46. data/lib/morpheus/cli/clouds.rb +15 -5
  47. data/lib/morpheus/cli/command_error.rb +7 -1
  48. data/lib/morpheus/cli/{alias_command.rb → commands/standard/alias_command.rb} +79 -51
  49. data/lib/morpheus/cli/commands/standard/benchmark_command.rb +399 -0
  50. data/lib/morpheus/cli/commands/standard/coloring_command.rb +60 -0
  51. data/lib/morpheus/cli/{curl_command.rb → commands/standard/curl_command.rb} +0 -7
  52. data/lib/morpheus/cli/commands/standard/debug_command.rb +61 -0
  53. data/lib/morpheus/cli/{echo_command.rb → commands/standard/echo_command.rb} +1 -1
  54. data/lib/morpheus/cli/{edit_profile_command.rb → commands/standard/edit_profile_command.rb} +0 -0
  55. data/lib/morpheus/cli/{edit_rc_command.rb → commands/standard/edit_rc_command.rb} +0 -0
  56. data/lib/morpheus/cli/commands/standard/get_prompt_command.rb +39 -0
  57. data/lib/morpheus/cli/commands/standard/history_command.rb +76 -0
  58. data/lib/morpheus/cli/{log_level_command.rb → commands/standard/log_level_command.rb} +1 -1
  59. data/lib/morpheus/cli/{man_command.rb → commands/standard/man_command.rb} +2 -2
  60. data/lib/morpheus/cli/commands/standard/rm_command.rb +14 -0
  61. data/lib/morpheus/cli/commands/standard/set_prompt_command.rb +54 -0
  62. data/lib/morpheus/cli/{sleep_command.rb → commands/standard/sleep_command.rb} +0 -0
  63. data/lib/morpheus/cli/{source_command.rb → commands/standard/source_command.rb} +0 -0
  64. data/lib/morpheus/cli/{ssl_verification_command.rb → commands/standard/ssl_verification_command.rb} +1 -1
  65. data/lib/morpheus/cli/commands/standard/tee_command.rb +14 -0
  66. data/lib/morpheus/cli/{version_command.rb → commands/standard/version_command.rb} +0 -0
  67. data/lib/morpheus/cli/credentials.rb +276 -87
  68. data/lib/morpheus/cli/cypher_command.rb +333 -214
  69. data/lib/morpheus/cli/error_handler.rb +12 -2
  70. data/lib/morpheus/cli/groups.rb +44 -20
  71. data/lib/morpheus/cli/hosts.rb +39 -16
  72. data/lib/morpheus/cli/instances.rb +114 -62
  73. data/lib/morpheus/cli/login.rb +74 -21
  74. data/lib/morpheus/cli/logout.rb +3 -4
  75. data/lib/morpheus/cli/mixins/accounts_helper.rb +50 -18
  76. data/lib/morpheus/cli/mixins/print_helper.rb +207 -42
  77. data/lib/morpheus/cli/old_cypher_command.rb +414 -0
  78. data/lib/morpheus/cli/option_parser.rb +6 -1
  79. data/lib/morpheus/cli/processes_command.rb +3 -0
  80. data/lib/morpheus/cli/remote.rb +11 -17
  81. data/lib/morpheus/cli/roles.rb +17 -17
  82. data/lib/morpheus/cli/security_groups.rb +47 -17
  83. data/lib/morpheus/cli/shell.rb +139 -79
  84. data/lib/morpheus/cli/tenants_command.rb +353 -0
  85. data/lib/morpheus/cli/users.rb +26 -18
  86. data/lib/morpheus/cli/version.rb +1 -1
  87. data/lib/morpheus/cli/whoami.rb +14 -10
  88. data/lib/morpheus/formatters.rb +4 -4
  89. data/lib/morpheus/logging.rb +16 -8
  90. data/lib/morpheus/terminal.rb +63 -34
  91. metadata +28 -15
  92. data/lib/morpheus/cli/coloring_command.rb +0 -45
  93. data/lib/morpheus/cli/set_prompt_command.rb +0 -51
@@ -18,7 +18,7 @@ class Morpheus::Cli::Login
18
18
  end
19
19
 
20
20
  def usage
21
- "Usage: morpheus login"
21
+ "Usage: morpheus login [username] [password]"
22
22
  end
23
23
 
24
24
  def handle(args)
@@ -36,13 +36,33 @@ class Morpheus::Cli::Login
36
36
  opts.on( '-p', '--password PASSWORD', "Password" ) do |val|
37
37
  password = val
38
38
  end
39
- opts.on( '-T', '--token ACCESS_TOKEN', "Use an existing access token instead of authenticating with a username and password." ) do |val|
39
+ opts.on( '-t', '--test', "Test credentials only, does not update stored credentials for the appliance." ) do
40
+ options[:test_only] = true
41
+ end
42
+ opts.on( '-T', '--token ACCESS_TOKEN', "Use an existing access token to login instead of authenticating with a username and password." ) do |val|
40
43
  options[:remote_token] = val
41
44
  end
42
- build_common_options(opts, options, [:json, :remote, :quiet])
45
+ build_common_options(opts, options, [:json, :dry_run, :remote, :quiet], [:remote_username, :remote_password, :remote_token])
46
+ opts.footer = "Login to a remote appliance with a username and password or an access token.\n" +
47
+ "[username] is required .\n" +
48
+ "[password] is required.\n" +
49
+ "Logging in with username and password will make an authentication api request to obtain an access token.\n" +
50
+ "The --token option can be used to login with an existing token instead of username and password.\n" +
51
+ "Using --token makes a whoami api request to validate the token.\n" +
52
+ "If successful, the access token will be saved with the active session for the remote appliance.\n" +
53
+ "This command will first logout any active session before attempting to login.\n" +
54
+ "The --test option can be used for testing credentials without updating your active session."
55
+
43
56
  end
44
57
  optparse.parse!(args)
45
-
58
+ if args.count > 2
59
+ print_error Morpheus::Terminal.angry_prompt
60
+ puts_error "#{command_name} list expects 0-2 arguments and received #{args.count}: #{args}\n#{optparse}"
61
+ return 1
62
+ end
63
+ username = args[0] if args[0]
64
+ password = args[1] if args[1]
65
+
46
66
  # connect(options)
47
67
  if options[:remote]
48
68
  appliance = Morpheus::Cli::Remote.appliances[options[:remote].to_sym]
@@ -53,41 +73,74 @@ class Morpheus::Cli::Login
53
73
  end
54
74
  if !@appliance_name
55
75
  print_error red, "You have no appliance named '#{options[:remote]}' configured. See the `remote list` command.", reset, "\n"
56
- return false
76
+ return 1
57
77
  end
78
+ elsif options[:remote_url]
79
+ # --remote-url
80
+ @appliance_name, @appliance_url = nil, appliance[:remote_url]
58
81
  else
59
82
  @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
60
83
  if !@appliance_name
61
84
  print_error yellow, "Please specify a remote appliance with -r or see the command `remote use`", reset, "\n"
62
- return false
85
+ return 1
63
86
  end
64
87
  end
65
88
 
66
89
  begin
67
- if options[:quiet]
68
- if ((!options[:remote_token]) && !(username && password))
69
- print_error yellow,"Please specify a username and password, or token.", reset, "\n"
70
- return false
71
- end
90
+ if (options[:quiet] && (!options[:remote_token]) && !(username && password))
91
+ print_error yellow,"Please specify username and password, or token.", reset, "\n"
92
+ return 1
72
93
  end
73
- options[:remote_username] = username if username
74
- options[:remote_password] = password if password
75
- #options[:remote_url] = true # will skip credentials save
76
- login_result = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).login(options)
77
94
 
78
- # check to see if we got credentials, or just look at login_result above...
79
- creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials() # .load_saved_credentials(true)
95
+ options[:username] = username if username
96
+ options[:password] = password if password
80
97
 
81
- # recalcuate echo vars
98
+ do_save = true
99
+ if options[:test_only] || options[:remote_url]
100
+ do_save = false
101
+ end
102
+ #old_wallet = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials()
103
+
104
+ login_result = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).login(options, do_save)
105
+ if options[:dry_run]
106
+ return 0
107
+ end
108
+ wallet = login_result
109
+
110
+ # needed here too?
82
111
  ::Morpheus::Cli::Remote.recalculate_variable_map()
83
112
 
84
- if creds
113
+ # should happen here, not in Credentials.login()
114
+ # if options[:json]
115
+ # puts as_json(login_result)
116
+ # return (login_result && login_result['access_token']) ? 0 : 1
117
+ # end
118
+
119
+ if wallet && wallet['access_token']
120
+ # Login Success!
85
121
  if !options[:quiet]
86
- print green,"Logged in to #{@appliance_name} as #{::Morpheus::Cli::Remote.load_remote(@appliance_name)[:username]}#{reset}", reset, "\n"
122
+ if options[:test_only]
123
+ print green,"Success! Credentials verified for #{wallet['username']}.", reset, "\n"
124
+ else
125
+ print green,"Success! Logged in to #{@appliance_name} as #{wallet['username']}.", reset, "\n"
126
+ end
87
127
  end
88
128
  return 0 # , nil
89
129
  else
90
- return 1 # , "Login failed"
130
+ # Login Failed
131
+ # so login() already prints 'Bad Credentials' (deprecate class Credentials plz)
132
+ # tell them if they're logged out now.
133
+ if !options[:quiet]
134
+ if options[:test_only]
135
+ # you are fine, nothing has changed
136
+ else
137
+ # if old_wallet && old_wallet['access_token']
138
+ # #print reset,"You are no longer logged in. Goodbye #{old_wallet['username']}!", reset, "\n"
139
+ # # todo: prompt to recover wallet ?
140
+ # end
141
+ end
142
+ end
143
+ return 1, "Login failed"
91
144
  end
92
145
 
93
146
  rescue RestClient::Exception => e
@@ -17,7 +17,6 @@ class Morpheus::Cli::Logout
17
17
 
18
18
  def connect(opts)
19
19
  #@api_client = establish_remote_appliance_connection(opts)
20
- #@access_token = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials(options)
21
20
  end
22
21
 
23
22
  def usage
@@ -45,8 +44,8 @@ class Morpheus::Cli::Logout
45
44
  puts_error "Please specify a Morpheus Appliance to logout of with -r or see the command `remote use`"
46
45
  return 1
47
46
  end
48
- creds = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url)
49
- token = creds.load_saved_credentials
47
+ wallet = Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).load_saved_credentials
48
+ token = wallet ? wallet['access_token'] : nil
50
49
  if !token
51
50
  if !options[:quiet]
52
51
  puts "You are not currently logged in to #{display_appliance(@appliance_name, @appliance_url)}"
@@ -57,7 +56,7 @@ class Morpheus::Cli::Logout
57
56
  # note: this also handles updating appliance session info
58
57
  Morpheus::Cli::Credentials.new(@appliance_name, @appliance_url).logout()
59
58
  if !options[:quiet]
60
- puts "#{cyan}Logged out of #{@appliance_name}. Goodbye.#{reset}"
59
+ puts "#{cyan}Logged out of #{@appliance_name}. Goodbye #{wallet['username']}!#{reset}"
61
60
  end
62
61
  end
63
62
  # recalcuate echo vars
@@ -110,7 +110,7 @@ module Morpheus::Cli::AccountsHelper
110
110
  return nil
111
111
  elsif roles.size > 1
112
112
  print_red_alert "#{roles.size} roles by name #{name}"
113
- print_roles_table(roles, {color: red})
113
+ print_roles_table(roles, {color: red, thin: true})
114
114
  print reset,"\n\n"
115
115
  return nil
116
116
  else
@@ -148,7 +148,7 @@ module Morpheus::Cli::AccountsHelper
148
148
  return nil
149
149
  elsif users.size > 1
150
150
  print_red_alert "#{users.size} users by username #{username}"
151
- print_users_table(users, {color: red})
151
+ print_users_table(users, {color: red, thin: true})
152
152
  print reset,"\n\n"
153
153
  return nil
154
154
  else
@@ -156,8 +156,32 @@ module Morpheus::Cli::AccountsHelper
156
156
  end
157
157
  end
158
158
 
159
- def print_accounts_table(accounts, opts={})
160
- table_color = opts[:color] || cyan
159
+ def find_all_user_ids(account_id, usernames)
160
+ user_ids = []
161
+ if usernames.is_a?(String)
162
+ usernames = usernames.split(",").collect {|it| it.to_s.strip }.select {|it| it }.uniq
163
+ else
164
+ usernames = usernames.collect {|it| it.to_s.strip }.select {|it| it }.uniq
165
+ end
166
+ usernames.each do |username|
167
+ # save a query
168
+ #user = find_user_by_username_or_id(nil, username)
169
+ if username.to_s =~ /\A\d{1,}\Z/
170
+ user_ids << username.to_i
171
+ else
172
+ user = find_user_by_username(account_id, username)
173
+ if user.nil?
174
+ return nil
175
+ else
176
+ user_ids << user['id']
177
+ end
178
+ end
179
+ end
180
+ user_ids
181
+ end
182
+
183
+ def print_accounts_table(accounts, options={})
184
+ table_color = options.key?(:color) ? options[:color] : cyan
161
185
  rows = accounts.collect do |account|
162
186
  status_state = nil
163
187
  if account['active']
@@ -205,8 +229,8 @@ module Morpheus::Cli::AccountsHelper
205
229
  return str
206
230
  end
207
231
 
208
- def print_roles_table(roles, opts={})
209
- table_color = opts[:color] || cyan
232
+ def print_roles_table(roles, options={})
233
+ table_color = options.key?(:color) ? options[:color] : cyan
210
234
  # tp roles, [
211
235
  # 'id',
212
236
  # 'name',
@@ -226,28 +250,36 @@ module Morpheus::Cli::AccountsHelper
226
250
  dateCreated: format_local_dt(role['dateCreated'])
227
251
  }
228
252
  end
229
- print table_color
230
- tp rows, [
253
+ columns = [
231
254
  :id,
232
255
  :name,
233
256
  :description,
234
- # opts[:is_master_account] ? :scope : nil,
235
- opts[:is_master_account] ? :type : nil,
236
- opts[:is_master_account] ? :multitenant : nil,
237
- opts[:is_master_account] ? :owner : nil,
257
+ # options[:is_master_account] ? :scope : nil,
258
+ options[:is_master_account] ? :type : nil,
259
+ options[:is_master_account] ? :multitenant : nil,
260
+ options[:is_master_account] ? :owner : nil,
238
261
  {:dateCreated => {:display_name => "Date Created"} }
239
262
  ].compact
240
- print reset
263
+ if options[:include_fields]
264
+ columns = options[:include_fields]
265
+ end
266
+ # print table_color if table_color
267
+ print as_pretty_table(rows, columns, options)
268
+ # print reset if table_color
241
269
  end
242
270
 
243
- def print_users_table(users, opts={})
244
- table_color = opts[:color] || cyan
271
+ def print_users_table(users, options={})
272
+ table_color = options[:color] || cyan
245
273
  rows = users.collect do |user|
246
274
  {id: user['id'], username: user['username'], name: user['displayName'], first: user['firstName'], last: user['lastName'], email: user['email'], role: format_user_role_names(user), account: user['account'] ? user['account']['name'] : nil}
247
275
  end
248
- print table_color
249
- tp rows, :id, :account, :first, :last, :username, :email, :role
250
- print reset
276
+ columns = [:id, :account, :first, :last, :username, :email, :role]
277
+ if options[:include_fields]
278
+ columns = options[:include_fields]
279
+ end
280
+ #print table_color if table_color
281
+ print as_pretty_table(rows, columns, options)
282
+ #print reset if table_color
251
283
  end
252
284
 
253
285
  def format_user_role_names(user)
@@ -4,6 +4,7 @@ require 'json'
4
4
  require 'yaml'
5
5
  require 'ostruct'
6
6
  require 'io/console'
7
+ require 'morpheus/logging'
7
8
 
8
9
  module Morpheus::Cli::PrintHelper
9
10
 
@@ -34,6 +35,7 @@ module Morpheus::Cli::PrintHelper
34
35
  end
35
36
 
36
37
  # puts red message to stderr
38
+ # why this not stderr yet? use print_error or if respond_to?(:my_terminal)
37
39
  def print_red_alert(msg)
38
40
  #$stderr.print "#{red}#{msg}#{reset}\n"
39
41
  print "#{red}#{msg}#{reset}\n"
@@ -51,9 +53,18 @@ module Morpheus::Cli::PrintHelper
51
53
  # title - subtitle1, subtitle2
52
54
  # ==================
53
55
  #
54
- def print_h1(title, subtitles=[], color=cyan)
55
- #print "\n" ,color, bold, title, (subtitles.empty? ? "" : " - #{subtitles.join(', ')}"), "\n", "==================", reset, "\n\n"
56
- subtitles = subtitles.flatten
56
+ def print_h1(title, subtitles=nil, options=nil)
57
+ # ok, support all these formats for now:
58
+ # print_h1(title, options={})
59
+ # print_h1(title, subtitles, options={})
60
+ # this can go away when we have a dirty @current_options
61
+ if subtitles.is_a?(Hash)
62
+ options = subtitles
63
+ subtitles = (options[:subtitles] || []).flatten
64
+ end
65
+ subtitles = (subtitles || []).flatten
66
+ options ||= {}
67
+ color = options[:color] || cyan
57
68
  out = ""
58
69
  out << "\n"
59
70
  out << "#{color}#{bold}#{title}#{reset}"
@@ -61,15 +72,27 @@ module Morpheus::Cli::PrintHelper
61
72
  out << "#{color} | #{subtitles.join(', ')}#{reset}"
62
73
  end
63
74
  out << "\n"
64
- out << "#{color}#{bold}==================#{reset}"
65
- out << "\n\n"
66
- out << reset
75
+ if options[:border_style] == :thin
76
+ out << "\n"
77
+ else
78
+ out << "#{color}#{bold}==================#{reset}\n\n"
79
+ end
67
80
  print out
68
81
  end
69
82
 
70
- def print_h2(title, subtitles=[], color=cyan)
71
- #print "\n" ,color, bold, title, (subtitles.empty? ? "" : " - #{subtitles.join(', ')}"), "\n", "---------------------", reset, "\n\n"
72
- subtitles = subtitles.flatten
83
+ def print_h2(title, subtitles=nil, options=nil)
84
+ # ok, support all these formats for now:
85
+ # print_h2(title={})
86
+ # print_h2(title, options={})
87
+ # print_h2(title, subtitles, options={})
88
+ # this can go away when we have a dirty @current_options
89
+ if subtitles.is_a?(Hash)
90
+ options = subtitles
91
+ subtitles = (options[:subtitles] || []).flatten
92
+ end
93
+ subtitles = (subtitles || []).flatten
94
+ options ||= {}
95
+ color = options[:color] || cyan
73
96
  out = ""
74
97
  out << "\n"
75
98
  out << "#{color}#{bold}#{title}#{reset}"
@@ -77,9 +100,11 @@ module Morpheus::Cli::PrintHelper
77
100
  out << "#{color} - #{subtitles.join(', ')}#{reset}"
78
101
  end
79
102
  out << "\n"
80
- out << "#{color}---------------------#{reset}"
81
- out << "\n\n"
82
- out << reset
103
+ if options[:border_style] == :thin
104
+ out << "\n"
105
+ else
106
+ out << "#{color}---------------------#{reset}\n\n"
107
+ end
83
108
  print out
84
109
  end
85
110
 
@@ -99,45 +124,92 @@ module Morpheus::Cli::PrintHelper
99
124
  end
100
125
  end
101
126
 
102
- def print_dry_run(opts, command_string=nil)
103
- http_method = opts[:method]
104
- url = opts[:url]
105
- params = opts[:params]
106
- params = opts[:headers][:params] if opts[:headers] && opts[:headers][:params]
107
- query_string = params.respond_to?(:map) ? URI.encode_www_form(params) : query_string
127
+ def print_dry_run(api_request, options={})
128
+ # 2nd argument used to be command_string (String)
129
+ command_string = nil
130
+ if options.is_a?(String)
131
+ command_string = options
132
+ options = {}
133
+ end
134
+ options ||= {}
135
+ # api client injects common command options here
136
+ if api_request[:command_options]
137
+ options = options.merge(api_request[:command_options])
138
+ end
139
+ options ||= {}
140
+ # parse params request arguments
141
+ http_method = api_request[:method]
142
+ url = api_request[:url]
143
+ headers = api_request[:headers]
144
+ params = nil
145
+ if api_request[:params] && !api_request[:params].empty?
146
+ params = api_request[:params]
147
+ elsif api_request[:headers] && api_request[:headers][:params]
148
+ # params inside headers for restclient reasons..
149
+ params = api_request[:headers][:params]
150
+ elsif api_request[:query] && !api_request[:query].empty?
151
+ params = api_request[:query]
152
+ end
153
+ query_string = params
154
+ if query_string.respond_to?(:map)
155
+ query_string = URI.encode_www_form(query_string)
156
+ end
108
157
  if query_string && !query_string.empty?
109
158
  url = "#{url}?#{query_string}"
110
159
  end
111
160
  request_string = "#{http_method.to_s.upcase} #{url}".strip
112
- payload = opts[:payload] || opts[:body]
113
- if command_string != false
114
- if command_string
115
- print_h1 "DRY RUN > #{command_string}"
116
- else
117
- print_h1 "DRY RUN"
118
- end
161
+ payload = api_request[:payload] || api_request[:body]
162
+
163
+ #Morpheus::Logging::DarkPrinter.puts "API payload is: (#{payload.class}) #{payload.inspect}"
164
+
165
+ # curl output?
166
+ if api_request[:curl] || options[:curl]
167
+ print "\n"
168
+ puts "#{cyan}#{bold}#{dark}CURL COMMAND#{reset}\n"
169
+ print format_curl_command(http_method, url, headers, payload, options)
170
+ print "\n",reset
171
+ return
119
172
  end
120
- print cyan
121
- print "Request: ", "\n"
122
- print reset
173
+
174
+ # print this thing:
175
+ # REQUEST:
176
+ # POST http://morpheusdata.com/api/whoami
177
+ # f it..removing this, just DRY RUN printed at the start of command
178
+ print "\n"
179
+ # if command_string != false
180
+ # if command_string
181
+ # print_h1 "DRY RUN > #{command_string}"
182
+ # else
183
+ # #print "\n"
184
+ # #print_h1 "DRY RUN"
185
+ # end
186
+ # end
187
+ puts "#{cyan}#{bold}#{dark}REQUEST#{reset}\n"
188
+ # print cyan
189
+ # print "Request: ", "\n"
190
+ # print reset
191
+ request_string = "#{http_method.to_s.upcase} #{url}".strip
123
192
  print request_string, "\n"
124
193
  print cyan
125
194
  if payload
126
- if payload.is_a?(String)
127
- begin
128
- payload = JSON.parse(payload)
129
- rescue => e
130
- #payload = "(unparsable) #{payload}"
131
- end
132
- end
195
+
133
196
  print "\n"
134
- if opts[:headers] && opts[:headers]['Content-Type'] == 'application/json'
135
- print "JSON: ", "\n"
136
- print reset
197
+ if api_request[:headers] && api_request[:headers]['Content-Type'] == 'application/json'
198
+ if payload.is_a?(String)
199
+ begin
200
+ payload = JSON.parse(payload)
201
+ rescue => e
202
+ #payload = "(unparsable) #{payload}"
203
+ end
204
+ end
205
+ puts "#{cyan}#{bold}#{dark}JSON#{reset}\n"
206
+ # print "JSON: ", "\n"
207
+ # print reset
137
208
  print JSON.pretty_generate(payload)
138
209
  else
139
- print "Content-Type: #{opts[:headers]['Content-Type']}", "\n"
140
- #print "BODY: ", "\n"
210
+ content_type = api_request[:headers]['Content-Type'] || 'application/x-www-form-urlencoded'
211
+ print "Content-Type: #{content_type}", "\n"
212
+ # print "Body: ", "\n"
141
213
  print reset
142
214
  if payload.is_a?(File)
143
215
  # pretty_size = Filesize.from("#{payload.size} B").pretty.strip
@@ -147,7 +219,17 @@ module Morpheus::Cli::PrintHelper
147
219
  elsif payload.is_a?(String)
148
220
  print payload
149
221
  else
150
- print payload.inspect
222
+ if content_type == 'application/x-www-form-urlencoded'
223
+ body_str = payload.to_s
224
+ begin
225
+ body_str = URI.encode_www_form(payload)
226
+ rescue => ex
227
+ # raise ex
228
+ end
229
+ print body_str
230
+ else
231
+ print payload
232
+ end
151
233
  end
152
234
  end
153
235
  end
@@ -155,6 +237,82 @@ module Morpheus::Cli::PrintHelper
155
237
  print reset
156
238
  end
157
239
 
240
+ # format_curl_command generates a valid curl command for the given api request
241
+ # @param api_request [Hash] api request, typically returned from api_client.dry.execute()
242
+ # @param options [Hash] common cli options
243
+ # formats command like:
244
+ #
245
+ # curl -XPOST "https://api.gomorpheus.com/api/cypher" \
246
+ # -H "Authorization: BEARER ******************" \
247
+ # -H "Content-Type: application/json" \
248
+ # -d '{
249
+ # "value": "mysecret"
250
+ # }'
251
+ def format_curl_command(http_method, url, headers, payload=nil, options={})
252
+ options ||= {}
253
+ # build curl [options]
254
+ out = ""
255
+ out << "curl -X#{http_method.to_s.upcase} '#{url}'"
256
+ if headers
257
+ headers.each do |k,v|
258
+ # avoid weird [:headers][:params]
259
+ unless k == :params
260
+ header_value = v
261
+ out << ' \\' + "\n"
262
+ header_line = " -H \"#{k.is_a?(Symbol) ? k.to_s.capitalize : k.to_s}: #{v}\""
263
+ out << header_line
264
+ end
265
+ end
266
+ end
267
+ if payload && !payload.empty?
268
+ out << + ' \\' + "\n"
269
+ if headers && headers['Content-Type'] == 'application/json'
270
+ if payload.is_a?(String)
271
+ begin
272
+ payload = JSON.parse(payload)
273
+ rescue => e
274
+ #payload = "(unparsable) #{payload}"
275
+ end
276
+ end
277
+ if payload.is_a?(Hash)
278
+ out << " -d '#{as_json(payload, options)}'"
279
+ else
280
+ out << " -d '#{payload}'"
281
+ end
282
+ else
283
+ content_type = headers['Content-Type'] || 'application/x-www-form-urlencoded'
284
+
285
+ if payload.is_a?(File)
286
+ # pretty_size = Filesize.from("#{payload.size} B").pretty.strip
287
+ pretty_size = "#{payload.size} B"
288
+ # print "File: #{payload.path} (#{payload.size} bytes)"
289
+ out << " -d @#{payload.path}"
290
+ elsif payload.is_a?(String)
291
+ out << " -d '#{payload}'"
292
+ else
293
+ if content_type == 'application/x-www-form-urlencoded'
294
+ body_str = payload.to_s
295
+ begin
296
+ body_str = URI.encode_www_form(payload)
297
+ rescue => ex
298
+ # raise ex
299
+ end
300
+ out << " -d '#{body_str}'"
301
+ else
302
+ out << " -d '#{payload}'"
303
+ end
304
+ end
305
+ end
306
+ out << "\n"
307
+ else
308
+ out << "\n"
309
+ end
310
+ if options[:scrub]
311
+ out = Morpheus::Logging.scrub_message(out)
312
+ end
313
+ return out
314
+
315
+ end
158
316
  def print_results_pagination(json_response, options={})
159
317
  # print cyan,"\nViewing #{json_response['meta']['offset'].to_i + 1}-#{json_response['meta']['offset'].to_i + json_response['meta']['size'].to_i} of #{json_response['meta']['total']}\n", reset
160
318
  print format_results_pagination(json_response, options)
@@ -473,7 +631,14 @@ module Morpheus::Cli::PrintHelper
473
631
  end
474
632
 
475
633
  # format header spacer row
476
- h_line = header_cells.collect {|cell| ("-" * cell.size) }.join(cell_delim.gsub(" ", "-"))
634
+ if options[:border_style] == :thin
635
+ # a simpler looking table
636
+ cell_delim = " "
637
+ h_line = header_cells.collect {|cell| ("-" * cell.strip.size).ljust(cell.size, ' ') }.join(cell_delim)
638
+ else
639
+ # default border style
640
+ h_line = header_cells.collect {|cell| ("-" * cell.size) }.join(cell_delim.gsub(" ", "-"))
641
+ end
477
642
 
478
643
  # format data rows
479
644
  formatted_rows = []