morpheus-cli 2.10.0 → 2.10.1

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/bin/morpheus +27 -32
  3. data/lib/morpheus/api/accounts_interface.rb +36 -47
  4. data/lib/morpheus/api/api_client.rb +141 -110
  5. data/lib/morpheus/api/app_templates_interface.rb +56 -72
  6. data/lib/morpheus/api/apps_interface.rb +111 -132
  7. data/lib/morpheus/api/auth_interface.rb +30 -0
  8. data/lib/morpheus/api/clouds_interface.rb +71 -76
  9. data/lib/morpheus/api/custom_instance_types_interface.rb +21 -46
  10. data/lib/morpheus/api/dashboard_interface.rb +10 -17
  11. data/lib/morpheus/api/deploy_interface.rb +60 -72
  12. data/lib/morpheus/api/deployments_interface.rb +53 -71
  13. data/lib/morpheus/api/groups_interface.rb +55 -45
  14. data/lib/morpheus/api/instance_types_interface.rb +19 -23
  15. data/lib/morpheus/api/instances_interface.rb +179 -177
  16. data/lib/morpheus/api/key_pairs_interface.rb +11 -17
  17. data/lib/morpheus/api/license_interface.rb +18 -23
  18. data/lib/morpheus/api/load_balancers_interface.rb +54 -69
  19. data/lib/morpheus/api/logs_interface.rb +25 -29
  20. data/lib/morpheus/api/options_interface.rb +13 -17
  21. data/lib/morpheus/api/provision_types_interface.rb +19 -22
  22. data/lib/morpheus/api/roles_interface.rb +75 -94
  23. data/lib/morpheus/api/security_group_rules_interface.rb +28 -37
  24. data/lib/morpheus/api/security_groups_interface.rb +39 -51
  25. data/lib/morpheus/api/servers_interface.rb +113 -115
  26. data/lib/morpheus/api/setup_interface.rb +31 -0
  27. data/lib/morpheus/api/task_sets_interface.rb +36 -38
  28. data/lib/morpheus/api/tasks_interface.rb +56 -69
  29. data/lib/morpheus/api/users_interface.rb +67 -76
  30. data/lib/morpheus/api/virtual_images_interface.rb +61 -61
  31. data/lib/morpheus/api/whoami_interface.rb +12 -15
  32. data/lib/morpheus/cli.rb +71 -60
  33. data/lib/morpheus/cli/accounts.rb +254 -315
  34. data/lib/morpheus/cli/alias_command.rb +219 -0
  35. data/lib/morpheus/cli/app_templates.rb +264 -272
  36. data/lib/morpheus/cli/apps.rb +608 -671
  37. data/lib/morpheus/cli/cli_command.rb +259 -21
  38. data/lib/morpheus/cli/cli_registry.rb +99 -14
  39. data/lib/morpheus/cli/clouds.rb +599 -372
  40. data/lib/morpheus/cli/config_file.rb +126 -0
  41. data/lib/morpheus/cli/credentials.rb +141 -117
  42. data/lib/morpheus/cli/dashboard_command.rb +48 -56
  43. data/lib/morpheus/cli/deployments.rb +254 -268
  44. data/lib/morpheus/cli/deploys.rb +150 -142
  45. data/lib/morpheus/cli/error_handler.rb +38 -0
  46. data/lib/morpheus/cli/groups.rb +551 -179
  47. data/lib/morpheus/cli/hosts.rb +862 -617
  48. data/lib/morpheus/cli/instance_types.rb +103 -95
  49. data/lib/morpheus/cli/instances.rb +1335 -1009
  50. data/lib/morpheus/cli/key_pairs.rb +82 -90
  51. data/lib/morpheus/cli/library.rb +498 -499
  52. data/lib/morpheus/cli/license.rb +83 -101
  53. data/lib/morpheus/cli/load_balancers.rb +314 -300
  54. data/lib/morpheus/cli/login.rb +66 -44
  55. data/lib/morpheus/cli/logout.rb +47 -46
  56. data/lib/morpheus/cli/mixins/accounts_helper.rb +69 -31
  57. data/lib/morpheus/cli/mixins/infrastructure_helper.rb +106 -0
  58. data/lib/morpheus/cli/mixins/print_helper.rb +181 -17
  59. data/lib/morpheus/cli/mixins/provisioning_helper.rb +535 -458
  60. data/lib/morpheus/cli/mixins/whoami_helper.rb +2 -2
  61. data/lib/morpheus/cli/option_parser.rb +35 -0
  62. data/lib/morpheus/cli/option_types.rb +232 -192
  63. data/lib/morpheus/cli/recent_activity_command.rb +61 -65
  64. data/lib/morpheus/cli/remote.rb +446 -199
  65. data/lib/morpheus/cli/roles.rb +884 -906
  66. data/lib/morpheus/cli/security_group_rules.rb +213 -203
  67. data/lib/morpheus/cli/security_groups.rb +237 -192
  68. data/lib/morpheus/cli/shell.rb +338 -231
  69. data/lib/morpheus/cli/tasks.rb +326 -308
  70. data/lib/morpheus/cli/users.rb +457 -462
  71. data/lib/morpheus/cli/version.rb +1 -1
  72. data/lib/morpheus/cli/version_command.rb +16 -18
  73. data/lib/morpheus/cli/virtual_images.rb +526 -345
  74. data/lib/morpheus/cli/whoami.rb +125 -111
  75. data/lib/morpheus/cli/workflows.rb +338 -185
  76. data/lib/morpheus/formatters.rb +8 -1
  77. data/lib/morpheus/logging.rb +1 -1
  78. data/lib/morpheus/rest_client.rb +17 -8
  79. metadata +9 -3
  80. data/lib/morpheus/api/custom_instance_types.rb +0 -55
@@ -1,82 +1,78 @@
1
1
  require 'optparse'
2
2
  require 'morpheus/cli/cli_command'
3
+ require 'morpheus/cli/mixins/accounts_helper'
3
4
  require 'json'
4
5
 
5
6
  class Morpheus::Cli::RecentActivityCommand
6
7
  include Morpheus::Cli::CliCommand
7
-
8
- cli_command_name :'recent-activity'
9
- cli_command_hidden # remove once this is done
8
+ include Morpheus::Cli::AccountsHelper
10
9
 
11
- def initialize()
12
- @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
13
- end
10
+ set_command_name :'recent-activity'
11
+ set_command_hidden # remove once this is done
14
12
 
15
- def connect(opts)
16
- @access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).load_saved_credentials()
17
- if @access_token.empty?
18
- print_red_alert "Invalid Credentials. Unable to acquire access token. Please verify your credentials and try again."
19
- exit 1
20
- end
21
- @api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
22
- @dashboard_interface = @api_client.dashboard
23
- end
13
+ def initialize()
14
+ # @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
15
+ end
24
16
 
25
- def usage
26
- "Usage: morpheus recent-activity"
27
- end
17
+ def connect(opts)
18
+ @api_client = establish_remote_appliance_connection(opts)
19
+ @dashboard_interface = @api_client.dashboard
20
+ @accounts_interface = @api_client.accounts
21
+ end
28
22
 
29
- def handle(args)
30
- list(args)
31
- end
32
-
33
- def list(args)
34
- options = {}
35
- optparse = OptionParser.new do|opts|
36
- opts.banner = usage
37
- opts.on(nil,'--start', "Start timestamp. Default is 30 days ago.") do |val|
38
- options[:start_ts] = val
39
- end
40
- opts.on(nil,'--end', "End timestamp. Default is now.") do |val|
41
- options[:end_ts] = val
42
- end
43
- build_common_options(opts, options, [:list, :json])
44
- end
45
- optparse.parse(args)
23
+ def usage
24
+ "Usage: morpheus #{command_name}"
25
+ end
46
26
 
47
- connect(options)
48
- begin
49
-
50
- params = {}
51
- [:phrase, :offset, :max, :sort, :direction, :start, :end].each do |k|
52
- params[k] = options[k] unless options[k].nil?
53
- end
27
+ def handle(args)
28
+ list(args)
29
+ end
30
+ def list(args)
31
+ options = {}
32
+ optparse = OptionParser.new do|opts|
33
+ opts.banner = usage
34
+ opts.on('--start TIMESTAMP','--start TIMESTAMP', "Start timestamp. Default is 30 days ago.") do |val|
35
+ options[:start] = parse_time(val).iso8601
36
+ end
37
+ opts.on('--end TIMESTAMP','--end TIMESTAMP', "End timestamp. Default is now.") do |val|
38
+ options[:end] = parse_time(val).iso8601
39
+ end
40
+ build_common_options(opts, options, [:account, :list, :json, :dry_run])
41
+ end
42
+ optparse.parse!(args)
43
+ connect(options)
44
+ begin
45
+ account = find_account_from_options(options)
46
+ account_id = account ? account['id'] : nil
47
+ params = {}
48
+ [:phrase, :offset, :max, :sort, :direction, :start, :end].each do |k|
49
+ params[k] = options[k] unless options[k].nil?
50
+ end
51
+ if options[:dry_run]
52
+ print_dry_run @dashboard_interface.dry.recent_activity(account_id, params)
53
+ return
54
+ end
55
+ json_response = @dashboard_interface.recent_activity(account_id, params)
56
+ if options[:json]
57
+ print JSON.pretty_generate(json_response)
58
+ print "\n"
59
+ else
54
60
 
55
- json_response = @dashboard_interface.recent_activity(params)
56
-
57
- if options[:json]
58
- print JSON.pretty_generate(json_response)
59
- print "\n"
60
- else
61
-
61
+ # todo: impersonate command and show that info here
62
62
 
63
- # todo: impersonate command and show that info here
63
+ print "\n" ,cyan, bold, "Dashboard\n","==================", reset, "\n\n"
64
+ print cyan
65
+ print "\n"
66
+ puts "Coming soon.... see --json"
67
+ print "\n"
64
68
 
65
- print "\n" ,cyan, bold, "Dashboard\n","==================", reset, "\n\n"
66
- print cyan
67
-
68
- print "\n"
69
- puts "Coming soon.... see --json"
70
- print "\n"
69
+ print reset,"\n"
71
70
 
72
- print reset,"\n"
73
-
74
- end
75
- rescue RestClient::Exception => e
76
- print_rest_exception(e, options)
77
- exit 1
78
- end
79
- end
80
-
71
+ end
72
+ rescue RestClient::Exception => e
73
+ print_rest_exception(e, options)
74
+ exit 1
75
+ end
76
+ end
81
77
 
82
78
  end
@@ -1,3 +1,4 @@
1
+ require 'fileutils'
1
2
  require 'yaml'
2
3
  require 'io/console'
3
4
  require 'rest_client'
@@ -6,203 +7,449 @@ require 'morpheus/cli/cli_command'
6
7
 
7
8
 
8
9
  class Morpheus::Cli::Remote
9
- include Morpheus::Cli::CliCommand
10
-
11
- def initialize()
12
- @appliances = ::Morpheus::Cli::Remote.load_appliance_file
13
- end
14
-
15
- def handle(args)
16
- if args.empty?
17
- puts "\nUsage: morpheus remote [list,add,remove,use] [name] [host]\n\n"
18
- return
19
- end
20
-
21
- case args[0]
22
- when 'list'
23
- list(args[1..-1])
24
- when 'add'
25
- add(args[1..-1])
26
- when 'remove'
27
- remove(args[1..-1])
28
- when 'use'
29
- use(args[1..-1])
30
- else
31
- puts "\nUsage: morpheus remote [list,add,remove,use] [name] [host]\n\n"
32
- end
33
- end
34
-
35
- def list(args)
36
- options = {}
37
- optparse = OptionParser.new do|opts|
38
- opts.banner = "Usage: morpheus remote list"
39
- build_common_options(opts, options, [])
40
- end
41
- optparse.parse(args)
42
-
43
- print "\n" ,cyan, bold, "Morpheus Appliances\n","==================", reset, "\n\n"
44
- # print red, bold, "red bold", reset, "\n"
45
- if @appliances == nil || @appliances.empty?
46
- puts yellow,"No remote appliances configured.",reset
47
- else
48
- rows = @appliances.collect do |app_name, v|
49
- {
50
- active: (v[:active] ? "=>" : ""),
51
- name: app_name,
52
- host: v[:host]
53
- }
54
- end
55
- print cyan
56
- tp rows, {:active => {:display_name => ""}}, {:name => {:width => 16}}, {:host => {:width => 40}}
57
- print reset
58
-
59
- # @appliances.each do |app_name, v|
60
- # print cyan
61
- # if v[:active] == true
62
- # print bold, "=> #{app_name}\t#{v[:host]}",reset,"\n"
63
- # else
64
- # print "= #{app_name}\t#{v[:host]}",reset,"\n"
65
- # end
66
- # end
67
-
68
- print "\n\n# => - current\n\n"
69
- end
70
- end
71
-
72
- def add(args)
73
- options = {}
74
- optparse = OptionParser.new do|opts|
75
- opts.banner = "Usage: morpheus remote add [name] [host] [--default]"
76
- build_common_options(opts, options, [])
77
- opts.on( '-d', '--default', "Make this the default remote appliance" ) do
78
- options[:default] = true
79
- end
80
- end
81
- optparse.parse(args)
82
- if args.count < 2
83
- puts "\n#{optparse.banner}\n\n"
84
- return
85
- end
86
-
87
- name = args[0].to_sym
88
- if @appliances[name] != nil
89
- print red, "Remote appliance already configured for #{args[0]}", reset, "\n"
90
- else
91
- @appliances[name] = {
92
- host: args[1],
93
- active: false
94
- }
95
- if options[:default] == true
96
- set_active_appliance name
97
- end
98
- end
99
- ::Morpheus::Cli::Remote.save_appliances(@appliances)
100
- list([])
101
- end
102
-
103
- def remove(args)
104
- options = {}
105
- optparse = OptionParser.new do|opts|
106
- opts.banner = "Usage: morpheus remote remove [name]"
107
- build_common_options(opts, options, [])
108
- opts.on( '-d', '--default', "Make this the default remote appliance" ) do
109
- options[:default] = true
110
- end
111
- end
112
- optparse.parse(args)
113
- if args.empty?
114
- puts "\n#{optparse.banner}\n\n"
115
- return
116
- end
117
-
118
- name = args[0].to_sym
119
- if @appliances[name] == nil
120
- print red, "Remote appliance not configured for #{args[0]}", reset, "\n"
121
- else
122
- active = false
123
- if @appliances[name][:active]
124
- active = true
125
- end
126
- @appliances.delete(name)
127
- if active && !@appliances.empty?
128
- @appliances[@appliances.keys.first][:active] = true
129
- end
130
- end
131
- ::Morpheus::Cli::Remote.save_appliances(@appliances)
132
- list([])
133
- end
134
-
135
- def use(args)
136
- options = {}
137
- optparse = OptionParser.new do|opts|
138
- opts.banner = "Usage: morpheus remote use [name]"
139
- build_common_options(opts, options, [])
140
- opts.on( '-d', '--default', "Make this the default remote appliance. This does the same thing as remote use." ) do
141
- options[:default] = true
142
- end
143
- end
144
- optparse.parse(args)
145
- if args.empty?
146
- puts "\n#{optparse.banner}\n\n"
147
- return
148
- end
149
-
150
- name = args[0].to_sym
151
- if @appliances[name] == nil
152
- print red, "Remote appliance not configured for #{args[0]}", reset, "\n"
153
- else
154
- set_active_appliance name
155
- end
156
- ::Morpheus::Cli::Remote.save_appliances(@appliances)
157
- list([])
158
- @@appliance = nil
159
- end
160
-
161
- def set_active_appliance(name)
162
- @appliances.each do |k,v|
163
- if k == name
164
- v[:active] = true
165
- else
166
- v[:active] = false
167
- end
168
- end
169
- end
170
-
171
- # Provides the current active appliance url information
172
- def self.active_appliance
173
- if !defined?(@@appliance) || @@appliance.nil?
174
- @@appliance = load_appliance_file.select { |k,v| v[:active] == true}
175
- end
176
- return @@appliance.keys[0], @@appliance[@@appliance.keys[0]][:host]
177
- end
178
-
179
-
180
-
181
- def self.load_appliance_file
182
- remote_file = appliances_file_path
183
- if File.exist? remote_file
184
- return YAML.load_file(remote_file)
185
- else
186
- return {}
187
- # return {
188
- # morpheus: {
189
- # host: 'https://api.gomorpheus.com',
190
- # active: true
191
- # }
192
- # }
193
- end
194
- end
195
-
196
- def self.appliances_file_path
197
- home_dir = Dir.home
198
- morpheus_dir = File.join(home_dir,".morpheus")
199
- if !Dir.exist?(morpheus_dir)
200
- Dir.mkdir(morpheus_dir)
201
- end
202
- return File.join(morpheus_dir,"appliances")
203
- end
204
-
205
- def self.save_appliances(appliance_map)
206
- File.open(appliances_file_path, 'w') {|f| f.write appliance_map.to_yaml } #Store
207
- end
10
+ include Morpheus::Cli::CliCommand
11
+
12
+ register_subcommands :list, :add, :remove, :use, :unuse, {:current => :print_current}, :setup
13
+ set_default_subcommand :list
14
+
15
+ def initialize()
16
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
17
+ end
18
+
19
+ def handle(args)
20
+ if args.count == 0
21
+ list(args)
22
+ else
23
+ handle_subcommand(args)
24
+ end
25
+ end
26
+
27
+ def list(args)
28
+ options = {}
29
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
30
+ opts.banner = subcommand_usage()
31
+ build_common_options(opts, options, [])
32
+ opts.footer = "This outputs a list of the remote appliances.\n" +
33
+ "It also displays the current active appliance.\n" +
34
+ "The shortcut `remote` can be used instead of `remote list`."
35
+ end
36
+ optparse.parse!(args)
37
+ @appliances = ::Morpheus::Cli::Remote.appliances
38
+ if @appliances == nil || @appliances.empty?
39
+ print yellow,"No remote appliances configured, see `remote add`",reset,"\n"
40
+ else
41
+ rows = @appliances.collect do |app_name, v|
42
+ {
43
+ active: (v[:active] ? "=>" : ""),
44
+ name: app_name,
45
+ host: v[:host]
46
+ }
47
+ end
48
+ print "\n" ,cyan, bold, "Morpheus Appliances\n","==================", reset, "\n\n"
49
+ print cyan
50
+ tp rows, {:active => {:display_name => ""}}, {:name => {:width => 16}}, {:host => {:width => 40}}
51
+ print reset
52
+ if @appliance_name
53
+ #unless @appliances.keys.size == 1
54
+ print cyan, "\n# => Currently using #{@appliance_name}\n", reset
55
+ #end
56
+ else
57
+ print "\n# => No active remote appliance, see `remote use`\n", reset
58
+ end
59
+ print "\n" # meh
60
+ end
61
+ end
62
+
63
+ def add(args)
64
+ options = {}
65
+ use_it = false
66
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
67
+ opts.banner = subcommand_usage("[name] [url]")
68
+ build_common_options(opts, options, [])
69
+ opts.on( '--use', '--use', "Make this the current remote appliance" ) do
70
+ use_it = true
71
+ end
72
+ # let's free up the -d switch for global options, maybe?
73
+ opts.on( '-d', '--default', "Does the same thing as --use" ) do
74
+ use_it = true
75
+ end
76
+ # todo: use Morpheus::Cli::OptionParser < OptionParser
77
+ # opts.on('-h', '--help', "Prints this help" ) do
78
+ # hidden_switches = ["--default"]
79
+ # good_opts = opts.to_s.split("\n").delete_if { |line| hidden_switches.find {|it| line =~ /#{Regexp.escape(it)}/ } }.join("\n")
80
+ # puts good_opts
81
+ # exit
82
+ # end
83
+ opts.footer = "This will add a new appliance to your list.\n" +
84
+ "If it's first one, it will be made the current active appliance."
85
+ end
86
+ optparse.parse!(args)
87
+ if args.count < 2
88
+ puts optparse
89
+ exit 1
90
+ end
91
+
92
+ new_appliance_name = args[0].to_sym
93
+ url = args[1]
94
+ if url !~ /^https?\:\/\//
95
+ print red, "The specified appliance url is invalid: '#{args[1]}'", reset, "\n"
96
+ puts optparse
97
+ exit 1
98
+ end
99
+ # maybe a ping here would be cool
100
+ @appliances = ::Morpheus::Cli::Remote.appliances
101
+ if @appliances.keys.empty?
102
+ use_it = true
103
+ end
104
+ if @appliances[new_appliance_name] != nil
105
+ print red, "Remote appliance already configured with the name '#{args[0]}'", reset, "\n"
106
+ else
107
+ @appliances[new_appliance_name] = {
108
+ host: url,
109
+ active: use_it
110
+ }
111
+ ::Morpheus::Cli::Remote.save_appliances(@appliances)
112
+ if use_it
113
+ #Morpheus::Cli::Remote.set_active_appliance(new_appliance_name)
114
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
115
+ end
116
+ end
117
+ #list([])
118
+ end
119
+
120
+ def remove(args)
121
+ options = {}
122
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
123
+ opts.banner = subcommand_usage("[name]")
124
+ opts.on( '-d', '--default', "Make this the default remote appliance" ) do
125
+ options[:default] = true
126
+ end
127
+ opts.footer = "This will delete an appliance from your list."
128
+ build_common_options(opts, options, [:auto_confirm])
129
+ end
130
+ optparse.parse!(args)
131
+ if args.empty?
132
+ puts optparse
133
+ exit 1
134
+ end
135
+ @appliances = ::Morpheus::Cli::Remote.appliances
136
+ appliance_name = args[0].to_sym
137
+ if @appliances[appliance_name] == nil
138
+ print red, "Remote appliance not found by the name '#{args[0]}'", reset, "\n"
139
+ else
140
+ unless options[:yes] || ::Morpheus::Cli::OptionTypes::confirm("Are you sure you would like to remove this remote appliance '#{appliance_name}'?", options)
141
+ exit 1
142
+ end
143
+ @appliances.delete(appliance_name)
144
+ ::Morpheus::Cli::Remote.save_appliances(@appliances)
145
+ # todo: also delete credentials and groups[appliance_name]
146
+ ::Morpheus::Cli::Groups.clear_active_group(appliance_name) # rescue nil
147
+ # this should be a class method too
148
+ #::Morpheus::Cli::Credentials.clear_saved_credentials(appliance_name)
149
+ ::Morpheus::Cli::Credentials.new(appliance_name, nil).clear_saved_credentials(appliance_name) # rescue nil
150
+ #list([])
151
+ end
152
+ end
153
+
154
+ def use(args)
155
+ options = {}
156
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
157
+ opts.banner = subcommand_usage("[name]")
158
+ build_common_options(opts, options, [])
159
+ opts.footer = "This allows you to switch between your different appliances."
160
+ end
161
+ optparse.parse!(args)
162
+ if args.count < 1
163
+ puts optparse
164
+ exit 1
165
+ end
166
+ new_appliance_name = args[0].to_sym
167
+ @appliances = ::Morpheus::Cli::Remote.appliances
168
+ if @appliance_name && @appliance_name.to_s == new_appliance_name.to_s
169
+ print reset,"Already using the appliance '#{args[0]}'","\n",reset
170
+ else
171
+ if @appliances[new_appliance_name] == nil
172
+ print red, "Remote appliance not found by the name '#{args[0]}'", reset, "\n"
173
+ return false
174
+ else
175
+ Morpheus::Cli::Remote.set_active_appliance(new_appliance_name)
176
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
177
+ #print cyan,"Switched to using appliance #{args[0]}","\n",reset
178
+ #list([])
179
+ end
180
+ end
181
+ end
182
+
183
+ def unuse(args)
184
+ options = {}
185
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
186
+ opts.banner = subcommand_usage()
187
+ opts.footer = "" +
188
+ "This will switch to no active appliance.\n" +
189
+ "You will need to use an appliance again, or pass the --remote option to your commands..\n"
190
+ build_common_options(opts, options, [])
191
+ end
192
+ optparse.parse!(args)
193
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
194
+ if @appliance_name
195
+ Morpheus::Cli::Remote.clear_active_appliance()
196
+ @appliance_name, @appliance_url = nil, nil
197
+ return true
198
+ else
199
+ puts "You are not using any appliance"
200
+ return false
201
+ end
202
+ end
203
+
204
+ def print_current(args)
205
+ options = {}
206
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
207
+ opts.banner = subcommand_usage()
208
+ build_common_options(opts, options, [:json])
209
+ end
210
+ optparse.parse!(args)
211
+
212
+ if @appliance_name
213
+ print cyan, @appliance_name,"\n",reset
214
+ else
215
+ print yellow, "No active appliance, see `remote use`\n", reset
216
+ return false
217
+ end
218
+ end
219
+
220
+ # this is a wizard that walks through the /api/setup controller
221
+ # it only needs to be used once to initialize a new appliance
222
+ def setup(args)
223
+ options = {}
224
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
225
+ opts.banner = subcommand_usage()
226
+ build_common_options(opts, options, [:options, :json, :dry_run])
227
+ opts.footer = "This can be used to initialize a new appliance.\n" +
228
+ "You will be prompted to create the master account.\n" +
229
+ "This is only available on a new, freshly installed, remote appliance."
230
+ end
231
+ optparse.parse!(args)
232
+
233
+ if !@appliance_name
234
+ print yellow, "No active appliance, see `remote use`\n", reset
235
+ return false
236
+ end
237
+
238
+ # this works without any authentication!
239
+ # it will allow anyone to use it, if there are no users/accounts in the system.
240
+ #@api_client = establish_remote_appliance_connection(options)
241
+ #@setup_interface = @api_client.setup
242
+ @setup_interface = Morpheus::SetupInterface.new(@appliance_url)
243
+ appliance_status_json = nil
244
+ begin
245
+ appliance_status_json = @setup_interface.get()
246
+ if appliance_status_json['success'] != true
247
+ print red, "Setup not available for appliance #{@appliance_name} - #{@appliance_url}.\n", reset
248
+ print red, "#{appliance_status_json['msg']}\n", reset
249
+ return false
250
+ end
251
+ rescue RestClient::Exception => e
252
+ print_rest_exception(e, options)
253
+ return false
254
+ end
255
+
256
+ payload = {}
257
+
258
+ if appliance_status_json['hubRegistrationEnabled']
259
+ link = File.join(@appliance_url, '/setup')
260
+ print red, "Sorry, setup with hub registration is not yet available.\n", reset
261
+ print "You can use the UI to setup your appliance.\n"
262
+ print "Go to #{link}\n", reset
263
+ # if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
264
+ # system "start #{link}"
265
+ # elsif RbConfig::CONFIG['host_os'] =~ /darwin/
266
+ # system "open #{link}"
267
+ # elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
268
+ # system "xdg-open #{link}"
269
+ # end
270
+ return false
271
+ else
272
+ print "\n" ,cyan, bold, "Morpheus Appliance Setup", "\n", "==================", reset, "\n\n"
273
+
274
+ puts "It looks like you're the first one here."
275
+ puts "Let's initialize your remote appliance at #{@appliance_url}"
276
+
277
+
278
+
279
+ # Master Account
280
+ print "\n" ,cyan, bold, "Create Master account", "\n", "==================", reset, "\n\n"
281
+ account_option_types = [
282
+ {'fieldName' => 'accountName', 'fieldLabel' => 'Master Account Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
283
+ ]
284
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(account_option_types, options[:options])
285
+ payload.merge!(v_prompt)
286
+
287
+ # Master User
288
+ print "\n" ,cyan, bold, "Create Master User", "\n", "==================", reset, "\n\n"
289
+ user_option_types = [
290
+ {'fieldName' => 'firstName', 'fieldLabel' => 'First Name', 'type' => 'text', 'required' => false, 'displayOrder' => 1},
291
+ {'fieldName' => 'lastName', 'fieldLabel' => 'Last Name', 'type' => 'text', 'required' => false, 'displayOrder' => 2},
292
+ {'fieldName' => 'username', 'fieldLabel' => 'Username', 'type' => 'text', 'required' => true, 'displayOrder' => 3},
293
+ {'fieldName' => 'email', 'fieldLabel' => 'Email', 'type' => 'text', 'required' => true, 'displayOrder' => 4},
294
+ ]
295
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(user_option_types, options[:options])
296
+ payload.merge!(v_prompt)
297
+
298
+ # Password prompt with re-prompting if no match
299
+ password_option_types = [
300
+ {'fieldName' => 'password', 'fieldLabel' => 'Password', 'type' => 'password', 'required' => true, 'displayOrder' => 6},
301
+ {'fieldName' => 'passwordConfirmation', 'fieldLabel' => 'Confirm Password', 'type' => 'password', 'required' => true, 'displayOrder' => 7},
302
+ ]
303
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(password_option_types, options[:options])
304
+ while v_prompt['passwordConfirmation'] != v_prompt['password']
305
+ print red, "Password confirmation does not match. Re-enter your new password.", reset, "\n"
306
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(password_option_types, options[:options])
307
+ end
308
+ payload.merge!(v_prompt)
309
+
310
+ # Extra settings
311
+ print "\n" ,cyan, bold, "Initial Setup", "\n", "==================", reset, "\n\n"
312
+ extra_option_types = [
313
+ {'fieldName' => 'applianceName', 'fieldLabel' => 'Appliance Name', 'type' => 'text', 'required' => true, 'defaultValue' => nil},
314
+ {'fieldName' => 'applianceUrl', 'fieldLabel' => 'Appliance URL', 'type' => 'text', 'required' => true, 'defaultValue' => appliance_status_json['applianceUrl']},
315
+ {'fieldName' => 'backups', 'fieldLabel' => 'Enable Backups', 'type' => 'checkbox', 'required' => false, 'defaultValue' => 'off'},
316
+ {'fieldName' => 'monitoring', 'fieldLabel' => 'Enable Monitoring', 'type' => 'checkbox', 'required' => false, 'defaultValue' => 'on'},
317
+ {'fieldName' => 'logs', 'fieldLabel' => 'Enable Logs', 'type' => 'checkbox', 'required' => false, 'defaultValue' => 'on'}
318
+ ]
319
+ v_prompt = Morpheus::Cli::OptionTypes.prompt(extra_option_types, options[:options])
320
+ payload.merge!(v_prompt)
321
+
322
+ begin
323
+ if options[:dry_run]
324
+ print_dry_run @setup_interface.dry.init(payload)
325
+ return
326
+ end
327
+ if !options[:json]
328
+ print "Initializing the appliance...\n"
329
+ end
330
+ json_response = @setup_interface.init(payload)
331
+ rescue RestClient::Exception => e
332
+ print_rest_exception(e, options)
333
+ return false
334
+ end
335
+
336
+ if options[:json]
337
+ print JSON.pretty_generate(json_response)
338
+ print "\n"
339
+ return
340
+ end
341
+ print "\n"
342
+ print cyan, "You have successfully setup the appliance.\n"
343
+ #print cyan, "You may now login with the command `login`.\n"
344
+ # uh, just use Credentials.login(username, password, {save: true})
345
+ cmd_res = Morpheus::Cli::Login.new.login(['--username', payload['username'], '--password', payload['password'], '-q'])
346
+ # print "\n"
347
+ print cyan, "You are now logged in as the System Admin #{payload['username']}.\n"
348
+ print reset
349
+ #print "\n"
350
+
351
+ if ::Morpheus::Cli::OptionTypes::confirm("Would you like to apply your License Key now?", options.merge({:default => true}))
352
+ cmd_res = Morpheus::Cli::License.new.apply([])
353
+ # license_is_valid = cmd_res != false
354
+ end
355
+
356
+ if ::Morpheus::Cli::OptionTypes::confirm("Do you want to create the first group now?", options.merge({:default => true}))
357
+ cmd_res = Morpheus::Cli::Groups.new.add(['--use'])
358
+
359
+ #print "\n"
360
+
361
+ # if cmd_res !=
362
+ if ::Morpheus::Cli::OptionTypes::confirm("Do you want to create the first cloud now?", options.merge({:default => true}))
363
+ cmd_res = Morpheus::Cli::Clouds.new.add([])
364
+ #print "\n"
365
+ end
366
+ # end
367
+ end
368
+ print "\n",reset
369
+
370
+ end
371
+ end
372
+
373
+ class << self
374
+ include Term::ANSIColor
375
+
376
+ # for caching the the contents of YAML file $home/appliances
377
+ # it is structured like :appliance_name => {:host => "htt[://api.gomorpheus.com", :active => true}
378
+ # not named @@appliances to avoid confusion with the instance variable . This is also a command class...
379
+ @@appliance_config = nil
380
+ #@@current_appliance = nil
381
+
382
+
383
+
384
+ def appliances
385
+ self.appliance_config
386
+ end
387
+
388
+ def appliance_config
389
+ @@appliance_config ||= load_appliance_file || {}
390
+ end
391
+
392
+ # Returns two things, the remote appliance name and url
393
+ def active_appliance
394
+ if self.appliances.empty?
395
+ return nil, nil
396
+ end
397
+ app_name, app_map = self.appliances.find {|k,v| v[:active] == true }
398
+ if app_name
399
+ return app_name, app_map[:host]
400
+ else
401
+ return app_name, nil
402
+ end
403
+ end
404
+
405
+ def set_active_appliance(name)
406
+ new_appliances = self.appliances
407
+ new_appliances.each do |k,v|
408
+ is_match = (name ? (k == name.to_sym) : false)
409
+ if is_match
410
+ v[:active] = true
411
+ else
412
+ v[:active] = false
413
+ end
414
+ end
415
+ save_appliances(new_appliances)
416
+ end
417
+
418
+ def clear_active_appliance
419
+ new_appliances = self.appliances
420
+ new_appliances.each do |k,v|
421
+ v[:active] = false
422
+ end
423
+ save_appliances(new_appliances)
424
+ end
425
+
426
+ def load_appliance_file
427
+ fn = appliances_file_path
428
+ if File.exist? fn
429
+ print "#{dark} #=> loading appliances file #{fn}#{reset}\n" if Morpheus::Logging.debug?
430
+ return YAML.load_file(fn)
431
+ else
432
+ return {}
433
+ # return {
434
+ # morpheus: {
435
+ # host: 'https://api.gomorpheus.com',
436
+ # active: true
437
+ # }
438
+ # }
439
+ end
440
+ end
441
+
442
+ def appliances_file_path
443
+ File.join(Morpheus::Cli.home_directory,"appliances")
444
+ end
445
+
446
+ def save_appliances(new_config)
447
+ File.open(appliances_file_path, 'w') {|f| f.write new_config.to_yaml } #Store
448
+ FileUtils.chmod(0600, appliances_file_path)
449
+ #@@appliance_config = load_appliance_file
450
+ @@appliance_config = new_config
451
+ end
452
+
453
+ end
454
+
208
455
  end