morpheus-cli 0.1.1 → 0.9.0

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/lib/morpheus/api/accounts_interface.rb +55 -0
  3. data/lib/morpheus/api/api_client.rb +48 -3
  4. data/lib/morpheus/api/apps_interface.rb +13 -13
  5. data/lib/morpheus/api/{zones_interface.rb → clouds_interface.rb} +10 -10
  6. data/lib/morpheus/api/deploy_interface.rb +4 -4
  7. data/lib/morpheus/api/groups_interface.rb +3 -3
  8. data/lib/morpheus/api/instance_types_interface.rb +2 -2
  9. data/lib/morpheus/api/instances_interface.rb +35 -19
  10. data/lib/morpheus/api/key_pairs_interface.rb +60 -0
  11. data/lib/morpheus/api/license_interface.rb +29 -0
  12. data/lib/morpheus/api/load_balancers_interface.rb +72 -0
  13. data/lib/morpheus/api/logs_interface.rb +37 -0
  14. data/lib/morpheus/api/options_interface.rb +20 -0
  15. data/lib/morpheus/api/provision_types_interface.rb +27 -0
  16. data/lib/morpheus/api/roles_interface.rb +73 -0
  17. data/lib/morpheus/api/security_group_rules_interface.rb +3 -3
  18. data/lib/morpheus/api/security_groups_interface.rb +5 -5
  19. data/lib/morpheus/api/servers_interface.rb +67 -3
  20. data/lib/morpheus/api/task_sets_interface.rb +46 -0
  21. data/lib/morpheus/api/tasks_interface.rb +72 -0
  22. data/lib/morpheus/api/users_interface.rb +72 -0
  23. data/lib/morpheus/cli.rb +27 -4
  24. data/lib/morpheus/cli/accounts.rb +306 -0
  25. data/lib/morpheus/cli/apps.rb +58 -1
  26. data/lib/morpheus/cli/cli_command.rb +87 -0
  27. data/lib/morpheus/cli/cli_registry.rb +6 -1
  28. data/lib/morpheus/cli/{zones.rb → clouds.rb} +99 -70
  29. data/lib/morpheus/cli/credentials.rb +23 -11
  30. data/lib/morpheus/cli/error_handler.rb +31 -11
  31. data/lib/morpheus/cli/groups.rb +1 -0
  32. data/lib/morpheus/cli/hosts.rb +567 -0
  33. data/lib/morpheus/cli/instances.rb +588 -292
  34. data/lib/morpheus/cli/key_pairs.rb +393 -0
  35. data/lib/morpheus/cli/license.rb +118 -0
  36. data/lib/morpheus/cli/load_balancers.rb +366 -0
  37. data/lib/morpheus/cli/mixins/accounts_helper.rb +193 -0
  38. data/lib/morpheus/cli/option_types.rb +260 -0
  39. data/lib/morpheus/cli/roles.rb +164 -0
  40. data/lib/morpheus/cli/security_group_rules.rb +4 -9
  41. data/lib/morpheus/cli/shell.rb +108 -0
  42. data/lib/morpheus/cli/tasks.rb +370 -0
  43. data/lib/morpheus/cli/users.rb +325 -0
  44. data/lib/morpheus/cli/version.rb +1 -1
  45. data/lib/morpheus/cli/workflows.rb +100 -0
  46. data/lib/morpheus/formatters.rb +43 -0
  47. data/morpheus-cli.gemspec +1 -1
  48. metadata +33 -10
  49. data/lib/morpheus/cli/servers.rb +0 -265
@@ -0,0 +1,260 @@
1
+ require 'term/ansicolor'
2
+
3
+ module Morpheus
4
+ module Cli
5
+ module OptionTypes
6
+ include Term::ANSIColor
7
+
8
+
9
+ def self.confirm(message,options={})
10
+ if options[:yes] == true
11
+ return true
12
+ end
13
+ value_found = false
14
+ while value_found == false do
15
+ print "#{message} (yes/no): "
16
+ input = $stdin.gets.chomp!
17
+ if input.downcase == 'yes'
18
+ return true
19
+ elsif input.downcase == 'no'
20
+ return false
21
+ else
22
+ puts "Invalid Option... Please try again."
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.prompt(option_types, options={}, api_client=nil,api_params={})
28
+ results = {}
29
+ options = options || {}
30
+ # puts "Options Prompt #{options}"
31
+ option_types.sort { |x,y| x['displayOrder'].to_i <=> y['displayOrder'].to_i }.each do |option_type|
32
+ context_map = results
33
+ value = nil
34
+ value_found=false
35
+ if option_type['fieldContext']
36
+ results[option_type['fieldContext']] ||= {}
37
+ context_map = results[option_type['fieldContext']]
38
+ if options[option_type['fieldContext']] and options[option_type['fieldContext']].key?(option_type['fieldLabel'])
39
+ value = options[option_type['fieldContext']][option_type['fieldLabel']]
40
+ value_found = true
41
+ end
42
+ end
43
+
44
+ if value_found == false && options.key?(option_type['fieldName'])
45
+ value = options[option_type['fieldName']]
46
+ value_found = true
47
+ end
48
+
49
+ if !value_found
50
+ if option_type['type'] == 'number'
51
+ value = number_prompt(option_type)
52
+ elsif option_type['type'] == 'password'
53
+ value = password_prompt(option_type)
54
+ elsif option_type['type'] == 'checkbox'
55
+ value = checkbox_prompt(option_type)
56
+ elsif option_type['type'] == 'radio'
57
+ value = radio_prompt(option_type)
58
+ elsif option_type['type'] == 'textarea'
59
+ value = multiline_prompt(option_type)
60
+ elsif option_type['type'] == 'code-editor'
61
+ value = multiline_prompt(option_type)
62
+ elsif option_type['type'] == 'select'
63
+ value = select_prompt(option_type,api_client, api_params)
64
+ elsif option_type['type'] == 'hidden'
65
+ value = option_type['defaultValue']
66
+ input = value
67
+ else
68
+ value = generic_prompt(option_type)
69
+ end
70
+
71
+ end
72
+ context_map[option_type['fieldName']] = value
73
+ end
74
+
75
+ return results
76
+ end
77
+
78
+
79
+ def self.radio_prompt(option_type)
80
+ value_found = false
81
+ value = nil
82
+ options = []
83
+ if option_type['config'] and option_type['config']['radioOptions']
84
+ option_type['config']['radioOptions'].each do |radio_option|
85
+ options << {key: radio_option['key'], checked: radio_option['checked']}
86
+ end
87
+ end
88
+ optionString = options.collect{ |b| b[:checked] ? "(#{b[:key]})" : b[:key]}.join(', ')
89
+ while !value_found do
90
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }[#{optionString}]: "
91
+ input = $stdin.gets.chomp!
92
+ if input == '?'
93
+ help_prompt(option_type)
94
+ else
95
+ if input.nil? || input.empty?
96
+ selectedOption = options.find{|o| o[:checked] == true}
97
+ else
98
+ selectedOption = options.find{|o| o[:key].downcase == input.downcase}
99
+ end
100
+
101
+ if selectedOption
102
+ value = selectedOption[:key]
103
+ else
104
+ puts "Invalid Option. Please select from #{optionString}."
105
+ end
106
+ if !value.nil? || option_type['required'] != true
107
+ value_found = true
108
+ end
109
+ end
110
+ end
111
+ return value
112
+ end
113
+
114
+ def self.number_prompt(option_type)
115
+ value_found = false
116
+ value = nil
117
+ while !value_found do
118
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}: "
119
+ input = $stdin.gets.chomp!
120
+ value = input.empty? ? option_type['defaultValue'] : input.to_i
121
+ if input == '?'
122
+ help_prompt(option_type)
123
+ elsif !value.nil? || option_type['required'] != true
124
+ value_found = true
125
+ end
126
+ end
127
+ return value
128
+ end
129
+
130
+ def self.select_prompt(option_type,api_client, api_params={})
131
+ value_found = false
132
+ value = nil
133
+ if option_type['optionSource']
134
+ source_options = load_source_options(option_type['optionSource'],api_client,api_params)
135
+ end
136
+ if !source_options['data'].nil? && !source_options['data'].count == 1 && option_type['skipSingleOption'] == true
137
+ value_found = true
138
+ value = source_option['value']
139
+ end
140
+ while !value_found do
141
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''} ['?' for options]: "
142
+ input = $stdin.gets.chomp!
143
+ if option_type['optionSource']
144
+ source_option = source_options.find{|b| b['name'] == input || (!b['value'].nil? && b['value'].to_s == input) || (b['value'].nil? && input.empty?)}
145
+ if source_option
146
+ value = source_option['value']
147
+ elsif !input.nil? && !input.empty?
148
+ input = '?'
149
+ end
150
+ else
151
+ value = input.empty? ? option_type['defaultValue'] : input
152
+ end
153
+
154
+ if input == '?'
155
+ help_prompt(option_type)
156
+ display_select_options(source_options)
157
+ elsif !value.nil? || option_type['required'] != true
158
+ value_found = true
159
+ end
160
+ end
161
+ return value
162
+ end
163
+
164
+ def self.checkbox_prompt(option_type)
165
+ value_found = false
166
+ value = nil
167
+ while !value_found do
168
+ print "#{option_type['fieldLabel']} (yes/no) [#{option_type['defaultValue'] == 'on' ? 'yes' : 'no'}]: "
169
+ input = $stdin.gets.chomp!
170
+ if input.downcase == 'yes'
171
+ value = 'on'
172
+ elsif input.downcase == 'no'
173
+ value = 'off'
174
+ else
175
+ value = option_type['defaultValue']
176
+ end
177
+ if input == '?'
178
+ help_prompt(option_type)
179
+ elsif !value.nil? || option_type['required'] != true
180
+ value_found = true
181
+ end
182
+ end
183
+ return value
184
+ end
185
+
186
+ def self.generic_prompt(option_type)
187
+ value_found = false
188
+ value = nil
189
+ while !value_found do
190
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}: "
191
+ input = $stdin.gets.chomp!
192
+ value = input.empty? ? option_type['defaultValue'] : input
193
+ if input == '?'
194
+ help_prompt(option_type)
195
+ elsif !value.nil? || option_type['required'] != true
196
+ value_found = true
197
+ end
198
+ end
199
+ return value
200
+ end
201
+
202
+ def self.multiline_prompt(option_type)
203
+ value_found = false
204
+ value = nil
205
+ while !value_found do
206
+ if value.nil?
207
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''} [Type 'EOF' to stop input]: \n"
208
+ end
209
+ input = $stdin.gets.chomp!
210
+ # value = input.empty? ? option_type['defaultValue'] : input
211
+ if input == '?' && value.nil?
212
+ help_prompt(option_type)
213
+ elsif (!value.nil? || option_type['required'] != true) && input.chomp == 'EOF'
214
+ value_found = true
215
+ else
216
+ if value.nil?
217
+ value = ''
218
+ end
219
+ value << input + "\n"
220
+ end
221
+ end
222
+ return value
223
+ end
224
+
225
+ def self.password_prompt(option_type)
226
+ value_found = false
227
+ while !value_found do
228
+ print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}: "
229
+ input = STDIN.noecho(&:gets).chomp!
230
+ value = input
231
+ print "\n"
232
+ if input == '?'
233
+ help_prompt(option_type)
234
+ elsif !value.nil? || option_type['required'] != true
235
+ value_found = true
236
+ end
237
+ end
238
+ return value
239
+ end
240
+
241
+ def self.help_prompt(option_type)
242
+ print Term::ANSIColor.green," * #{option_type['fieldLabel']} [-O #{option_type['fieldName']}=] - ", Term::ANSIColor.reset , "#{option_type['description']}\n"
243
+ end
244
+
245
+
246
+ def self.load_source_options(source,api_client,params)
247
+ api_client.options.options_for_source(source,params)['data']
248
+ end
249
+
250
+ def self.display_select_options(select_options = [])
251
+ puts "\nOptions"
252
+ puts "==============="
253
+ select_options.each do |option|
254
+ puts " * #{option['name']} [#{option['value']}]"
255
+ end
256
+ puts "\n\n"
257
+ end
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,164 @@
1
+ # require 'yaml'
2
+ require 'io/console'
3
+ require 'rest_client'
4
+ require 'term/ansicolor'
5
+ require 'optparse'
6
+ require 'morpheus/cli/cli_command'
7
+ require 'morpheus/cli/option_types'
8
+ require 'morpheus/cli/mixins/accounts_helper'
9
+ require 'json'
10
+
11
+ class Morpheus::Cli::Roles
12
+ include Term::ANSIColor
13
+ include Morpheus::Cli::CliCommand
14
+ include Morpheus::Cli::AccountsHelper
15
+
16
+ def initialize()
17
+ @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
18
+ #@active_groups = ::Morpheus::Cli::Groups.load_group_file
19
+ end
20
+
21
+ def connect(opts)
22
+ @access_token = Morpheus::Cli::Credentials.new(@appliance_name,@appliance_url).request_credentials()
23
+ if @access_token.empty?
24
+ print red,bold, "\nInvalid Credentials. Unable to acquire access token. Please verify your credentials and try again.\n\n",reset
25
+ exit 1
26
+ end
27
+ @api_client = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url)
28
+ @users_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).users
29
+ @accounts_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).accounts
30
+ @roles_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).roles
31
+ end
32
+
33
+ def handle(args)
34
+ if args.empty?
35
+ puts "\nUsage: morpheus roles [list]\n\n"
36
+ exit 1
37
+ end
38
+
39
+ case args[0]
40
+ when 'list'
41
+ list(args[1..-1])
42
+ when 'details'
43
+ details(args[1..-1])
44
+ when 'add'
45
+ add(args[1..-1])
46
+ when 'remove'
47
+ remove(args[1..-1])
48
+ else
49
+ puts "\nUsage: morpheus hosts [list] \n\n"
50
+ exit 127
51
+ end
52
+ end
53
+
54
+ def list(args)
55
+ account_name = nil
56
+ options = {}
57
+ params = {}
58
+ optparse = OptionParser.new do|opts|
59
+ Morpheus::Cli::CliCommand.accountScopeOptions(opts,options)
60
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
61
+ end
62
+ optparse.parse(args)
63
+ connect(options)
64
+ begin
65
+ account_id = nil
66
+ if !account_name.nil?
67
+ account = find_account_by_name(account_name)
68
+ exit 1 if account.nil?
69
+ account_id = account['id']
70
+ end
71
+
72
+ [:phrase, :offset, :max, :sort, :direction].each do |k|
73
+ params[k] = options[k] unless options[k].nil?
74
+ end
75
+
76
+ json_response = @roles_interface.list(account_id, params)
77
+ roles = json_response['roles']
78
+
79
+ if options[:json]
80
+ print JSON.pretty_generate(json_response)
81
+ print "\n"
82
+ else
83
+ print "\n" ,cyan, bold, "Morpheus Roles\n","==================", reset, "\n\n"
84
+ if roles.empty?
85
+ puts yellow,"No roles found.",reset
86
+ else
87
+ print_roles_table(roles)
88
+ end
89
+ print reset,"\n\n"
90
+ end
91
+ rescue RestClient::Exception => e
92
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
93
+ exit 1
94
+ end
95
+ end
96
+
97
+ def details(args)
98
+ usage = "Usage: morpheus roles details [name] [options]"
99
+ if args.count < 1
100
+ puts "\n#{usage}\n\n"
101
+ exit 1
102
+ end
103
+ account = nil
104
+ name = args[0]
105
+ options = {}
106
+ params = {}
107
+ optparse = OptionParser.new do|opts|
108
+ opts.banner = usage
109
+ Morpheus::Cli::CliCommand.accountScopeOptions(opts,options)
110
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
111
+ end
112
+ optparse.parse(args)
113
+ connect(options)
114
+ begin
115
+
116
+ account = find_account_from_options(options)
117
+ account_id = account ? account['id'] : nil
118
+
119
+ # todo: roles_response = @roles_interface.list(account_id, {name: name}) instead
120
+ # there may be response data outside of role that needs to be displayed
121
+ role = find_role_by_name(account_id, name)
122
+ exit 1 if role.nil?
123
+
124
+ if options[:json]
125
+ print JSON.pretty_generate(role)
126
+ print "\n"
127
+ else
128
+ print "\n" ,cyan, bold, "Role Details\n","==================", reset, "\n\n"
129
+ print cyan
130
+ puts "ID: #{role['id']}"
131
+ puts "Name: #{role['authority']}"
132
+ puts "Description: #{role['description']}"
133
+ puts "Scope: #{role['scope']}"
134
+ puts "Owner: #{role['owner'] ? role['owner']['name'] : nil}"
135
+ puts "Date Created: #{format_local_dt(role['dateCreated'])}"
136
+ puts "Last Updated: #{format_local_dt(role['lastUpdated'])}"
137
+ print "\n" ,cyan, bold, "Role Instance Limits\n","==================", reset, "\n\n"
138
+ print cyan
139
+ puts "Max Storage (bytes): #{role['instanceLimits'] ? role['instanceLimits']['maxStorage'] : 0}"
140
+ puts "Max Memory (bytes): #{role['instanceLimits'] ? role['instanceLimits']['maxMemory'] : 0}"
141
+ puts "CPU Count: #{role['instanceLimits'] ? role['instanceLimits']['maxCpu'] : 0}"
142
+ print cyan
143
+ print reset,"\n\n"
144
+ end
145
+ rescue RestClient::Exception => e
146
+ ::Morpheus::Cli::ErrorHandler.new.print_rest_exception(e)
147
+ exit 1
148
+ end
149
+ end
150
+
151
+ def add(args)
152
+ print red,bold, "\nNOT YET IMPLEMENTED!\n\n",reset
153
+ exit 1
154
+ end
155
+
156
+ def remove(args)
157
+ print red,bold, "\nNOT YET IMPLEMENTED!\n\n",reset
158
+ exit 1
159
+ end
160
+
161
+ private
162
+
163
+
164
+ end
@@ -58,7 +58,7 @@ EOT
58
58
  security_group_id = nil
59
59
  optparse = OptionParser.new do|opts|
60
60
  opts.banner = "\nUsage: morpheus security-group-rules add_custom_rule SOURCE_CIDR PORT_RANGE PROTOCOL [options]"
61
- opts.on( '-s', '--secgroup secgroup', "Security Group ID (Use will use security as set with 'security-groups use id'" ) do |id|
61
+ opts.on( '-s', '--secgroup SECGROUP', "Security Group ID (Use will use security as set with 'security-groups use id'" ) do |id|
62
62
  security_group_id = id
63
63
  end
64
64
  opts.on( '-h', '--help', "Prints this help" ) do
@@ -158,15 +158,10 @@ EOT
158
158
  options = {}
159
159
  security_group_id = nil
160
160
  optparse = OptionParser.new do|opts|
161
- opts.banner = "\nUsage: morpheus security-group-rules list [options]"
162
- opts.on( '-s', '--secgroup secgroup', "Security Group ID (Use will use security as set with 'security-groups use id'" ) do |id|
163
- security_group_id = id
164
- end
165
- opts.on( '-h', '--help', "Prints this help" ) do
166
- puts opts
167
- exit
168
- end
161
+ opts.banner = "\nUsage: morpheus security-group-rules list [ID]"
162
+ Morpheus::Cli::CliCommand.genericOptions(opts,options)
169
163
  end
164
+ security_group_id = args[0].to_i
170
165
  optparse.parse(args)
171
166
 
172
167
  if security_group_id.nil?