morpheus-cli 3.6.8 → 3.6.9

Sign up to get free protection for your applications and to get access to all the features.
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 = []