morpheus-cli 2.10.1 → 2.10.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,207 @@
1
+ require 'fileutils'
2
+ require 'time'
3
+ require 'morpheus/cli/cli_registry'
4
+ require 'morpheus/logging'
5
+ require 'term/ansicolor'
6
+
7
+ class Morpheus::Cli::DotFile
8
+ include Term::ANSIColor
9
+
10
+ DEFAULT_EXEC_PROC = lambda {|args|
11
+
12
+ }
13
+ EXPORTED_ALIASES_HEADER = "# exported aliases"
14
+
15
+ # the path of the profile source file
16
+ # this is executed when `morpheus` is run
17
+ def self.morpheus_profile_filename
18
+ File.join(Morpheus::Cli.home_directory, ".morpheus_profile")
19
+ end
20
+
21
+ # the path of the shell source file
22
+ # this is executed when `morpheus shell` is run
23
+ def self.morpheusrc_filename
24
+ File.join(Morpheus::Cli.home_directory, ".morpheusrc")
25
+ end
26
+
27
+ attr_reader :filename
28
+ attr_reader :file_contents
29
+ attr_reader :commands
30
+ attr_reader :cmd_results
31
+
32
+ def initialize(fn)
33
+ @filename = fn
34
+ #load_file()
35
+ end
36
+
37
+ # execute this file as a morpheus shell script
38
+ # @param stop_on_failure [true, false] the will halt execution if a command returns false.
39
+ # Default is false, keep going...
40
+ # @block [Proc] if a block is given, each command in the file will be yielded to it
41
+ # The default is executes the command with the CliRegistry.exec(cmd, args)
42
+ # @return [Array] exit codes of all the commands that were run.
43
+ def execute(stop_on_failure=false, &block)
44
+ if !File.exists?(@filename)
45
+ print "#{Term::ANSIColor.red}source file not found: #{@filename}#{Term::ANSIColor.reset}\n" # if Morpheus::Logging.debug?
46
+ else
47
+ print "#{dark} #=> executing source file #{@filename}#{reset}\n" if Morpheus::Logging.debug?
48
+ end
49
+ file_contents ||= File.read(@filename)
50
+ lines = file_contents.split("\n")
51
+ cmd_results = []
52
+ line_num = 0
53
+ lines.each_with_index do |line, line_index|
54
+ line_num = line_index + 1
55
+ line = line.strip
56
+ next if line.empty?
57
+ next if line =~ /^\#/ # skip comments
58
+
59
+ # print "#{dark} #=> executing source file line #{line_num}: #{line}#{reset}\n" if Morpheus::Logging.debug?
60
+
61
+ # todo: allow semicolons inside arguments too..
62
+ command_list = line.strip.split(';').compact
63
+ command_list.each do |input|
64
+ input = input.strip
65
+ if input.empty?
66
+ next
67
+ end
68
+ argv = Shellwords.shellsplit(input)
69
+
70
+ if Morpheus::Cli::CliRegistry.has_command?(argv[0]) || Morpheus::Cli::CliRegistry.has_alias?(argv[0])
71
+ #log_history_command(input)
72
+ cmd_result = nil
73
+ begin
74
+ cmd_result = Morpheus::Cli::CliRegistry.exec(argv[0], argv[1..-1])
75
+ rescue SystemExit => err
76
+ if err.success?
77
+ cmd_result = true
78
+ else
79
+ puts "#{red} source file: #{@filename} line: #{line_num} command: #{argv[0]}#{reset} error: exited non zero - #{err}"
80
+ cmd_result = false
81
+ end
82
+ rescue => err
83
+ # raise err
84
+ puts "#{red} source file: #{@filename} line: #{line_num} command: #{argv[0]}#{reset} error: unexpected error - #{err}"
85
+ cmd_result = false
86
+ end
87
+ cmd_results << cmd_result
88
+ # next command please!
89
+ else
90
+ puts "#{red}Unrecognized source command file: #{@filename} line: #{line_num} command: #{argv[0]}#{reset}"
91
+ cmd_result = false
92
+ end
93
+ if cmd_result == false
94
+ if stop_on_failure
95
+ return cmd_results
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+ return cmd_results
102
+ end
103
+
104
+ # this saves the source file, upserting alias definitions at the bottom
105
+ # todo: smarter logic to allow the user to put stuff AFTER this section too
106
+ # under the section titled '# exported aliases'
107
+ # @param alias_definitions [Map] Map of alias_name => command_string
108
+ # @return nil
109
+ def export_aliases(alias_definitions)
110
+ if !@filename
111
+ print "#{Term::ANSIColor.dark}Skipping source file save because filename has not been set#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
112
+ return false
113
+ end
114
+ if !Dir.exists?(File.dirname(@filename))
115
+ FileUtils.mkdir_p(File.dirname(@filename))
116
+ end
117
+ if !File.exists?(@filename)
118
+ print "#{Term::ANSIColor.dark}Initializing source file #{@filename}#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
119
+ FileUtils.touch(@filename)
120
+ else
121
+ print "#{dark} #=> Saving source file #{@filename}#{reset}\n" if Morpheus::Logging.debug?
122
+ end
123
+
124
+
125
+ config_text = File.read(@filename)
126
+ config_lines = config_text.split(/\n/)
127
+ new_config_lines = []
128
+ existing_alias_definitions = {}
129
+ header_line_index = config_lines.index {|line| line.strip.include?(EXPORTED_ALIASES_HEADER) }
130
+ if header_line_index
131
+ # keep everything before the exported alias section
132
+ new_config_lines = config_lines[0..header_line_index-1]
133
+ existing_alias_lines = config_lines[header_line_index..config_lines.size-1]
134
+ # parse out the existing alias definitions
135
+ existing_alias_lines.each do |line|
136
+ if line =~ /^alias\s+/
137
+ alias_name, command_string = Morpheus::Cli::CliRegistry.parse_alias_definition(line)
138
+ if alias_name.empty? || command_string.empty?
139
+ print "#{dark} #=> removing bad config line #{line_num} invalid alias definition: #{line}\n" if Morpheus::Logging.debug?
140
+ else
141
+ existing_alias_definitions[alias_name] = command_string
142
+ end
143
+ end
144
+ end
145
+ else
146
+ new_config_lines = config_lines
147
+ new_config_lines << "" # blank line before alias header
148
+ end
149
+
150
+ # append header line
151
+ new_config_lines << EXPORTED_ALIASES_HEADER
152
+ new_config_lines << "# Do not put anything below here, or it will be lost when aliases are exported"
153
+ #new_config_lines << ""
154
+
155
+ # update aliases, sort them, and append the lines
156
+ new_alias_definitions = existing_alias_definitions.merge(alias_definitions)
157
+ new_alias_definitions.keys.sort.each do |alias_name|
158
+ new_config_lines << "alias #{alias_name}='#{new_alias_definitions[alias_name]}'"
159
+ end
160
+
161
+ # include a blank line after this section
162
+ new_config_lines << ""
163
+ new_config_lines << ""
164
+
165
+ new_config_text = new_config_lines.join("\n")
166
+
167
+ File.open(@filename, 'w') {|f| f.write(new_config_text) }
168
+ return true
169
+ end
170
+
171
+ # this saves the source file, removing alias definitions at the bottom
172
+ # todo: smarter logic to allow the user to put stuff AFTER this section too
173
+ # under the section titled '# exported aliases'
174
+ # @param alias_definitions [Map] Map of alias_name => command_string
175
+ # @return nil
176
+ def remove_aliases(alias_names)
177
+ if !@filename
178
+ print "#{Term::ANSIColor.dark}Skipping source file save because filename has not been set#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
179
+ return false
180
+ end
181
+ if !Dir.exists?(File.dirname(@filename))
182
+ FileUtils.mkdir_p(File.dirname(@filename))
183
+ end
184
+ if !File.exists?(@filename)
185
+ print "#{Term::ANSIColor.dark}Initializing source file #{@filename}#{Term::ANSIColor.reset}\n" if Morpheus::Logging.debug?
186
+ FileUtils.touch(@filename)
187
+ else
188
+ print "#{dark} #=> Saving source file #{@filename}#{reset}\n" if Morpheus::Logging.debug?
189
+ end
190
+
191
+
192
+ config_text = File.read(@filename)
193
+ config_lines = config_text.split(/\n/)
194
+
195
+ new_config_lines = config_lines.reject {|line|
196
+ alias_names.find {|alias_name| /^alias\s+#{Regexp.escape(alias_name)}\s?\=/ }
197
+ }
198
+
199
+ new_config_text = new_config_lines.join("\n")
200
+
201
+ File.open(@filename, 'w') {|f| f.write(new_config_text) }
202
+ return true
203
+ end
204
+
205
+
206
+
207
+ end
@@ -0,0 +1,32 @@
1
+ require 'optparse'
2
+ require 'morpheus/cli/cli_command'
3
+ require 'json'
4
+
5
+ # This is for use in dotfile scripts
6
+ class Morpheus::Cli::EchoCommand
7
+ include Morpheus::Cli::CliCommand
8
+ set_command_name :echo
9
+ set_command_hidden
10
+
11
+ def handle(args)
12
+ append_newline = true
13
+ options = {}
14
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
15
+ opts.banner = "Usage: morpheus #{command_name} [<message>]"
16
+ opts.on( '-n', '--nonewline', "do not append a newline to your words" ) do
17
+ append_newline = false
18
+ end
19
+ build_common_options(opts, options, [])
20
+ end
21
+ optparse.parse!(args)
22
+ out = ""
23
+ out << args.join(' ')
24
+ if append_newline
25
+ out << "\n"
26
+ end
27
+ # print out
28
+ print cyan + out + reset
29
+ return true
30
+ end
31
+
32
+ end
@@ -12,12 +12,14 @@ class Morpheus::Cli::ErrorHandler
12
12
  end
13
13
  case (err)
14
14
  when OptionParser::InvalidOption, OptionParser::AmbiguousOption, OptionParser::MissingArgument, OptionParser::InvalidArgument
15
- # raise e
15
+ # raise err
16
16
  print_red_alert "#{err.message}"
17
17
  puts "Try -h for help with this command."
18
18
  when Errno::ECONNREFUSED
19
19
  print_red_alert "#{err.message}"
20
20
  # more special errors?
21
+ when OpenSSL::SSL::SSLError
22
+ print_red_alert "Error Communicating with the Appliance. #{err.message}"
21
23
  when RestClient::Exception
22
24
  print_rest_exception(err, options)
23
25
  else
@@ -128,12 +128,14 @@ class Morpheus::Cli::Groups
128
128
  use_it = false
129
129
  optparse = Morpheus::Cli::OptionParser.new do|opts|
130
130
  opts.banner = subcommand_usage("[name]")
131
- opts.on( '-l', '--location LOCATION', "Location" ) do |val|
132
- params[:location] = val
133
- end
131
+ build_option_type_options(opts, options, add_group_option_types())
132
+ # opts.on( '-l', '--location LOCATION', "Location" ) do |val|
133
+ # params[:location] = val
134
+ # end
134
135
  opts.on( '--use', '--use', "Make this the current active group" ) do
135
136
  use_it = true
136
137
  end
138
+
137
139
  build_common_options(opts, options, [:options, :json, :dry_run, :remote])
138
140
  opts.footer = "Create a new group."
139
141
  end
@@ -187,9 +189,10 @@ class Morpheus::Cli::Groups
187
189
  params = {}
188
190
  optparse = Morpheus::Cli::OptionParser.new do|opts|
189
191
  opts.banner = subcommand_usage("[name] [options]")
190
- opts.on( '-l', '--location LOCATION', "Location" ) do |val|
191
- params[:location] = val
192
- end
192
+ build_option_type_options(opts, options, update_group_option_types())
193
+ # opts.on( '-l', '--location LOCATION', "Location" ) do |val|
194
+ # params[:location] = val
195
+ # end
193
196
  build_common_options(opts, options, [:options, :json, :dry_run, :remote])
194
197
  opts.footer = "Update an existing group."
195
198
  end
@@ -203,13 +206,11 @@ class Morpheus::Cli::Groups
203
206
  group = find_group_by_name_or_id(args[0])
204
207
  group_payload = {id: group['id']}
205
208
 
206
- all_option_types = update_group_option_types()
207
- #params = Morpheus::Cli::OptionTypes.prompt(all_option_types, options[:options], @api_client, {})
209
+ #params = Morpheus::Cli::OptionTypes.prompt(update_group_option_types, options[:options], @api_client, {})
208
210
  params = options[:options] || {}
209
211
 
210
212
  if params.empty?
211
- puts optparse.banner
212
- print_available_options(all_option_types)
213
+ puts optparse
213
214
  exit 1
214
215
  end
215
216
 
@@ -364,8 +365,8 @@ class Morpheus::Cli::Groups
364
365
  optparse = Morpheus::Cli::OptionParser.new do|opts|
365
366
  opts.banner = subcommand_usage("[name]")
366
367
  opts.footer = "" +
367
- "This sets the current active group.\n" +
368
- "It will be auto-selected for use during provisioning.\n" +
368
+ "This sets the active group.\n" +
369
+ "The active group will be auto-selected for use during provisioning.\n" +
369
370
  "You can still use the --group option to override this."
370
371
  build_common_options(opts, options, [])
371
372
  end
@@ -401,9 +402,10 @@ class Morpheus::Cli::Groups
401
402
  def unuse(args)
402
403
  options = {}
403
404
  optparse = Morpheus::Cli::OptionParser.new do|opts|
404
- opts.banner = subcommand_usage() + "\n\n" +
405
- "This will clear the active group." + "\n" +
406
- "You will be prompted for a Group during provisioning." + "\n\n"
405
+ opts.banner = subcommand_usage()
406
+ opts.footer = "" +
407
+ "This will clear the current active group.\n" +
408
+ "You will be prompted for a Group during provisioning."
407
409
  build_common_options(opts, options, [])
408
410
  end
409
411
  optparse.parse!(args)
@@ -429,10 +431,7 @@ class Morpheus::Cli::Groups
429
431
  optparse = Morpheus::Cli::OptionParser.new do|opts|
430
432
  opts.banner = subcommand_usage()
431
433
  build_common_options(opts, options, [])
432
- opts.footer = "" +
433
- "This will set the current remote appliance.\n" +
434
- "It will be used for all subsequent commands.\n" +
435
- "You may still use the --remote option to override this."
434
+ opts.footer = "Prints the name of the current active group"
436
435
  end
437
436
  optparse.parse!(args)
438
437
  connect(options)
@@ -509,7 +508,6 @@ public
509
508
  end
510
509
 
511
510
  # Provides the current active group information (just the ID right now)
512
- # appliance_name should probably be required.. or just use this instead: Groups.active_groups[appliance_name]
513
511
  def active_group(appliance_name=nil)
514
512
  if appliance_name == nil
515
513
  appliance_name, appliance_url = Morpheus::Cli::Remote.active_appliance
@@ -10,7 +10,7 @@ require 'json'
10
10
  class Morpheus::Cli::Hosts
11
11
  include Morpheus::Cli::CliCommand
12
12
  include Morpheus::Cli::ProvisioningHelper
13
- register_subcommands :list, :get, :stats, :add, :remove, :logs, :start, :stop, :resize, :run_workflow, :make_managed, :upgrade_agent, :server_types
13
+ register_subcommands :list, :get, :stats, :add, :remove, :logs, :start, :stop, :resize, :run_workflow, {:'make-managed' => :install_agent}, :upgrade_agent, :server_types
14
14
  alias_subcommand :details, :get
15
15
  set_default_subcommand :list
16
16
 
@@ -147,6 +147,11 @@ class Morpheus::Cli::Hosts
147
147
  puts "Type: #{server['computeServerType'] ? server['computeServerType']['name'] : 'unmanaged'}"
148
148
  puts "Platform: #{server['serverOs'] ? server['serverOs']['name'].upcase : 'N/A'}"
149
149
  puts "Plan: #{server['plan'] ? server['plan']['name'] : ''}"
150
+ if server['agentInstalled']
151
+ puts "Agent: #{server['agentVersion'] || ''} updated at #{format_local_dt(server['lastAgentUpdate'])}"
152
+ else
153
+ puts "Agent: (not installed)"
154
+ end
150
155
  puts "Status: #{format_host_status(server)}"
151
156
  puts "Power: #{format_server_power_state(server)}"
152
157
  if ((stats['maxMemory'].to_i != 0) || (stats['maxStorage'].to_i != 0))
@@ -325,7 +330,7 @@ class Morpheus::Cli::Hosts
325
330
  opts.on( '-t', '--type TYPE', "Server Type Code" ) do |val|
326
331
  options[:server_type_code] = val
327
332
  end
328
- build_common_options(opts, options, [:options, :json, :dry_run, :remote])
333
+ build_common_options(opts, options, [:options, :json, :dry_run, :quiet, :remote])
329
334
  end
330
335
  optparse.parse!(args)
331
336
  connect(options)
@@ -457,8 +462,8 @@ class Morpheus::Cli::Hosts
457
462
  if options[:json]
458
463
  print JSON.pretty_generate(json_response)
459
464
  print "\n"
460
- else
461
- print_green_success "Provisioning Server..."
465
+ elsif !options[:quiet]
466
+ print_green_success "Provisioning Server..."
462
467
  list([])
463
468
  end
464
469
  rescue RestClient::Exception => e
@@ -478,7 +483,7 @@ class Morpheus::Cli::Hosts
478
483
  opts.on( '-S', '--skip-remove-infrastructure', "Skip removal of underlying cloud infrastructure" ) do
479
484
  query_params[:removeResources] = 'off'
480
485
  end
481
- build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :remote])
486
+ build_common_options(opts, options, [:auto_confirm, :json, :dry_run, :quiet, :remote])
482
487
  end
483
488
  optparse.parse!(args)
484
489
  if args.count < 1
@@ -500,9 +505,9 @@ class Morpheus::Cli::Hosts
500
505
  if options[:json]
501
506
  print JSON.pretty_generate(json_response)
502
507
  print "\n"
503
- else
504
- print_green_success "Removing Server..."
505
- list([])
508
+ elsif !options[:quiet]
509
+ print_green_success "Host #{server['name']} is being removed..."
510
+ #list([])
506
511
  end
507
512
  rescue RestClient::Exception => e
508
513
  print_rest_exception(e, options)
@@ -514,7 +519,7 @@ class Morpheus::Cli::Hosts
514
519
  options = {}
515
520
  optparse = OptionParser.new do|opts|
516
521
  opts.banner = subcommand_usage("[name]")
517
- build_common_options(opts, options, [:json, :remote])
522
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
518
523
  end
519
524
  optparse.parse!(args)
520
525
  if args.count < 1
@@ -524,12 +529,16 @@ class Morpheus::Cli::Hosts
524
529
  connect(options)
525
530
  begin
526
531
  host = find_host_by_name_or_id(args[0])
532
+ if options[:dry_run]
533
+ print_dry_run @servers_interface.dry.start(host['id'])
534
+ return
535
+ end
527
536
  json_response = @servers_interface.start(host['id'])
528
537
  if options[:json]
529
538
  print JSON.pretty_generate(json_response)
530
539
  print "\n"
531
- else
532
- puts "Host #{host['name']} started."
540
+ elsif !options[:quiet]
541
+ print_green_success "Host #{host['name']} started."
533
542
  end
534
543
  return
535
544
  rescue RestClient::Exception => e
@@ -542,7 +551,7 @@ class Morpheus::Cli::Hosts
542
551
  options = {}
543
552
  optparse = OptionParser.new do|opts|
544
553
  opts.banner = subcommand_usage("[name]")
545
- build_common_options(opts, options, [:json, :remote])
554
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
546
555
  end
547
556
  optparse.parse!(args)
548
557
  if args.count < 1
@@ -560,8 +569,8 @@ class Morpheus::Cli::Hosts
560
569
  if options[:json]
561
570
  print JSON.pretty_generate(json_response)
562
571
  print "\n"
563
- else
564
- puts "Host #{host['name']} stopped." unless options[:quiet]
572
+ elsif !options[:quiet]
573
+ puts "Host #{host['name']} stopped."
565
574
  end
566
575
  return
567
576
  rescue RestClient::Exception => e
@@ -654,7 +663,7 @@ class Morpheus::Cli::Hosts
654
663
  print "\n"
655
664
  else
656
665
  unless options[:quiet]
657
- print_green_success "Resizing server #{server['name']}"
666
+ puts "Host #{server['name']} resizing..."
658
667
  list([])
659
668
  end
660
669
  end
@@ -664,11 +673,63 @@ class Morpheus::Cli::Hosts
664
673
  end
665
674
  end
666
675
 
667
- def upgrade(args)
676
+ def install_agent(args)
677
+ options = {}
678
+ optparse = OptionParser.new do|opts|
679
+ opts.banner = subcommand_usage("[name]")
680
+ build_option_type_options(opts, options, install_agent_option_types(false))
681
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
682
+ end
683
+ optparse.parse!(args)
684
+ if args.count < 1
685
+ puts optparse
686
+ exit 1
687
+ end
688
+ connect(options)
689
+ begin
690
+ host = find_host_by_name_or_id(args[0])
691
+ if host['agentInstalled']
692
+ print_red_alert "Agent already installed on host '#{host['name']}'"
693
+ return false
694
+ end
695
+ payload = {
696
+ 'server' => {}
697
+ }
698
+ params = Morpheus::Cli::OptionTypes.prompt(install_agent_option_types, options[:options], @api_client, options[:params])
699
+ server_os = params.delete('serverOs')
700
+ if server_os
701
+ payload['server']['serverOs'] = {id: server_os}
702
+ end
703
+ account_id = params.delete('account') # not yet implemented
704
+ if account_id
705
+ payload['server']['account'] = {id: account}
706
+ end
707
+ payload['server'].merge!(params)
708
+
709
+ if options[:dry_run]
710
+ print_dry_run @servers_interface.dry.install_agent(host['id'], payload)
711
+ return
712
+ end
713
+ json_response = @servers_interface.install_agent(host['id'], payload)
714
+ if options[:json]
715
+ print JSON.pretty_generate(json_response)
716
+ print "\n"
717
+ elsif !options[:quiet]
718
+ print_green_success "Host #{host['name']} is being converted to managed."
719
+ puts "Public Key:\n#{json_response['publicKey']}\n(copy to your authorized_keys file)"
720
+ end
721
+ return true
722
+ rescue RestClient::Exception => e
723
+ print_rest_exception(e, options)
724
+ exit 1
725
+ end
726
+ end
727
+
728
+ def upgrade_agent(args)
668
729
  options = {}
669
730
  optparse = OptionParser.new do|opts|
670
731
  opts.banner = subcommand_usage("[name]")
671
- build_common_options(opts, options, [:json, :quiet, :remote])
732
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
672
733
  end
673
734
  optparse.parse!(args)
674
735
  if args.count < 1
@@ -678,6 +739,10 @@ class Morpheus::Cli::Hosts
678
739
  connect(options)
679
740
  begin
680
741
  host = find_host_by_name_or_id(args[0])
742
+ if options[:dry_run]
743
+ print_dry_run @servers_interface.dry.upgrade(host['id'])
744
+ return
745
+ end
681
746
  json_response = @servers_interface.upgrade(host['id'])
682
747
  if options[:json]
683
748
  print JSON.pretty_generate(json_response)
@@ -696,13 +761,13 @@ class Morpheus::Cli::Hosts
696
761
  options = {}
697
762
  optparse = OptionParser.new do|opts|
698
763
  opts.banner = subcommand_usage("run-workflow", "[name]", "[workflow]")
699
- build_common_options(opts, options, [:json, :dry_run, :remote])
764
+ build_common_options(opts, options, [:json, :dry_run, :quiet, :remote])
700
765
  end
766
+ optparse.parse!(args)
701
767
  if args.count < 2
702
- puts "\n#{optparse}\n\n"
768
+ puts optparse
703
769
  exit 1
704
770
  end
705
- optparse.parse!(args)
706
771
  connect(options)
707
772
  host = find_host_by_name_or_id(args[0])
708
773
  workflow = find_workflow_by_name(args[1])
@@ -738,8 +803,8 @@ class Morpheus::Cli::Hosts
738
803
  if options[:json]
739
804
  print JSON.pretty_generate(json_response)
740
805
  print "\n"
741
- else
742
- puts "Running workflow..."
806
+ elsif !options[:quiet]
807
+ puts "Workflow #{workflow['name']} is running..."
743
808
  end
744
809
  rescue RestClient::Exception => e
745
810
  print_rest_exception(e, options)
@@ -873,4 +938,13 @@ class Morpheus::Cli::Hosts
873
938
  out
874
939
  end
875
940
 
941
+ def install_agent_option_types(connected=true)
942
+ [
943
+ #{'fieldName' => 'account', 'fieldLabel' => 'Account', 'type' => 'select', 'optionSource' => 'accounts', 'required' => true},
944
+ {'fieldName' => 'sshUsername', 'fieldLabel' => 'SSH Username', 'type' => 'text', 'required' => true},
945
+ {'fieldName' => 'sshPassword', 'fieldLabel' => 'SSH Password', 'type' => 'password', 'required' => false},
946
+ {'fieldName' => 'serverOs', 'fieldLabel' => 'OS Type', 'type' => 'select', 'optionSource' => 'osTypes', 'required' => false},
947
+ ]
948
+ end
949
+
876
950
  end