morpheus-cli 2.10.1 → 2.10.2

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.
@@ -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