morpheus-cli 8.0.12.2 → 8.1.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.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/bin/morpheus +7 -4
- data/lib/morpheus/api/api_client.rb +8 -0
- data/lib/morpheus/api/roles_interface.rb +14 -0
- data/lib/morpheus/api/system_types_interface.rb +13 -0
- data/lib/morpheus/api/systems_interface.rb +9 -0
- data/lib/morpheus/cli/commands/backups_command.rb +31 -0
- data/lib/morpheus/cli/commands/catalog_item_types_command.rb +8 -12
- data/lib/morpheus/cli/commands/clusters.rb +18 -14
- data/lib/morpheus/cli/commands/library_option_lists_command.rb +10 -2
- data/lib/morpheus/cli/commands/roles.rb +333 -38
- data/lib/morpheus/cli/commands/service_plans_command.rb +7 -0
- data/lib/morpheus/cli/commands/storage_providers_command.rb +6 -2
- data/lib/morpheus/cli/commands/systems.rb +270 -0
- data/lib/morpheus/cli/commands/tenants_command.rb +12 -3
- data/lib/morpheus/cli/mixins/accounts_helper.rb +1 -0
- data/lib/morpheus/cli/mixins/backups_helper.rb +29 -1
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +5 -2
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
|
2
|
+
|
|
3
|
+
class Morpheus::Cli::Systems
|
|
4
|
+
include Morpheus::Cli::CliCommand
|
|
5
|
+
include Morpheus::Cli::RestCommand
|
|
6
|
+
|
|
7
|
+
set_command_name :systems
|
|
8
|
+
set_command_description "View and manage systems."
|
|
9
|
+
register_subcommands :list, :get, :add, :update, :remove
|
|
10
|
+
|
|
11
|
+
set_command_hidden
|
|
12
|
+
|
|
13
|
+
protected
|
|
14
|
+
|
|
15
|
+
# Systems API uses lowercase keys in payloads.
|
|
16
|
+
def system_object_key
|
|
17
|
+
'system'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def system_list_key
|
|
21
|
+
'systems'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def system_list_column_definitions(options)
|
|
25
|
+
{
|
|
26
|
+
"ID" => 'id',
|
|
27
|
+
"Name" => 'name',
|
|
28
|
+
"Type" => lambda {|it| it['type'] ? it['type']['name'] : '' },
|
|
29
|
+
"Layout" => lambda {|it| it['layout'] ? it['layout']['name'] : '' },
|
|
30
|
+
"Status" => 'status',
|
|
31
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
|
32
|
+
"Date Created" => lambda {|it| format_local_dt(it['dateCreated']) }
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def system_column_definitions(options)
|
|
37
|
+
{
|
|
38
|
+
"ID" => 'id',
|
|
39
|
+
"Name" => 'name',
|
|
40
|
+
"Description" => 'description',
|
|
41
|
+
"Status" => 'status',
|
|
42
|
+
"Status Message" => 'statusMessage',
|
|
43
|
+
"Enabled" => lambda {|it| format_boolean(it['enabled']) },
|
|
44
|
+
"External ID" => 'externalId',
|
|
45
|
+
"Date Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
|
46
|
+
"Last Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def render_response_for_get(json_response, options)
|
|
51
|
+
render_response(json_response, options, rest_object_key) do
|
|
52
|
+
record = json_response[rest_object_key] || json_response
|
|
53
|
+
print_h1 rest_label, [], options
|
|
54
|
+
print cyan
|
|
55
|
+
print_description_list(rest_column_definitions(options), record, options)
|
|
56
|
+
print reset,"\n"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def add(args)
|
|
61
|
+
options = {}
|
|
62
|
+
params = {}
|
|
63
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
64
|
+
opts.banner = subcommand_usage("[name]")
|
|
65
|
+
opts.on('--name NAME', String, "System Name") do |val|
|
|
66
|
+
params['name'] = val.to_s
|
|
67
|
+
end
|
|
68
|
+
opts.on('--description [TEXT]', String, "Description") do |val|
|
|
69
|
+
params['description'] = val.to_s
|
|
70
|
+
end
|
|
71
|
+
opts.on('--type TYPE', String, "System Type ID or name") do |val|
|
|
72
|
+
params['type'] = val
|
|
73
|
+
end
|
|
74
|
+
opts.on('--layout LAYOUT', String, "System Layout ID or name") do |val|
|
|
75
|
+
params['layout'] = val
|
|
76
|
+
end
|
|
77
|
+
build_standard_add_options(opts, options)
|
|
78
|
+
opts.footer = "Create a new system.\n[name] is optional and can be passed as the first argument."
|
|
79
|
+
end
|
|
80
|
+
optparse.parse!(args)
|
|
81
|
+
connect(options)
|
|
82
|
+
|
|
83
|
+
payload = nil
|
|
84
|
+
if options[:payload]
|
|
85
|
+
payload = options[:payload]
|
|
86
|
+
payload[rest_object_key] ||= {}
|
|
87
|
+
payload[rest_object_key].deep_merge!(params) unless params.empty?
|
|
88
|
+
payload[rest_object_key]['name'] ||= args[0] if args[0]
|
|
89
|
+
else
|
|
90
|
+
system_payload = {}
|
|
91
|
+
|
|
92
|
+
# Name
|
|
93
|
+
system_payload['name'] = params['name'] || args[0]
|
|
94
|
+
if !system_payload['name'] && !options[:no_prompt]
|
|
95
|
+
system_payload['name'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => 'Name', 'required' => true}], options[:options], @api_client, {})['name']
|
|
96
|
+
end
|
|
97
|
+
raise_command_error "Name is required.\n#{optparse}" if system_payload['name'].to_s.empty?
|
|
98
|
+
|
|
99
|
+
# Description
|
|
100
|
+
if !params['description'] && !options[:no_prompt]
|
|
101
|
+
system_payload['description'] = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'type' => 'text', 'fieldLabel' => 'Description', 'required' => false}], options[:options], @api_client, {})['description']
|
|
102
|
+
else
|
|
103
|
+
system_payload['description'] = params['description']
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Type
|
|
107
|
+
available_types = system_types_for_dropdown
|
|
108
|
+
type_val = params['type']
|
|
109
|
+
if type_val
|
|
110
|
+
type_id = type_val =~ /\A\d+\Z/ ? type_val.to_i : available_types.find { |t| t['name'] == type_val || t['code'] == type_val }&.dig('id')
|
|
111
|
+
raise_command_error "System type not found: #{type_val}" unless type_id
|
|
112
|
+
system_payload['type'] = {'id' => type_id}
|
|
113
|
+
elsif !options[:no_prompt]
|
|
114
|
+
if available_types.empty?
|
|
115
|
+
raise_command_error "No system types found."
|
|
116
|
+
else
|
|
117
|
+
print cyan, "Available System Types\n", reset
|
|
118
|
+
available_types.each do |t|
|
|
119
|
+
print " #{t['id']}) #{t['name']}#{t['code'] ? " (#{t['code']})" : ''}\n"
|
|
120
|
+
end
|
|
121
|
+
selected = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'type' => 'text', 'fieldLabel' => 'System Type ID', 'required' => true}], options[:options], @api_client, {})['type']
|
|
122
|
+
type_id = available_types.find { |t| t['id'].to_s == selected.to_s }&.dig('id')
|
|
123
|
+
raise_command_error "Invalid system type id: #{selected}" unless type_id
|
|
124
|
+
system_payload['type'] = {'id' => type_id}
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Layout
|
|
129
|
+
available_layouts = system_layouts_for_dropdown(system_payload.dig('type', 'id'))
|
|
130
|
+
layout_val = params['layout']
|
|
131
|
+
if layout_val
|
|
132
|
+
layout_id = layout_val =~ /\A\d+\Z/ ? layout_val.to_i : available_layouts.find { |l| l['name'] == layout_val || l['code'] == layout_val }&.dig('id')
|
|
133
|
+
raise_command_error "System layout not found: #{layout_val}" unless layout_id
|
|
134
|
+
system_payload['layout'] = {'id' => layout_id}
|
|
135
|
+
elsif !options[:no_prompt]
|
|
136
|
+
if available_layouts.empty?
|
|
137
|
+
raise_command_error "No system layouts found for selected type."
|
|
138
|
+
else
|
|
139
|
+
print cyan, "Available System Layouts\n", reset
|
|
140
|
+
available_layouts.each do |l|
|
|
141
|
+
print " #{l['id']}) #{l['name']}#{l['code'] ? " (#{l['code']})" : ''}\n"
|
|
142
|
+
end
|
|
143
|
+
selected = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'layout', 'type' => 'text', 'fieldLabel' => 'System Layout ID', 'required' => true}], options[:options], @api_client, {})['layout']
|
|
144
|
+
layout_id = available_layouts.find { |l| l['id'].to_s == selected.to_s }&.dig('id')
|
|
145
|
+
raise_command_error "Invalid system layout id: #{selected}" unless layout_id
|
|
146
|
+
system_payload['layout'] = {'id' => layout_id}
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
payload = {rest_object_key => system_payload}
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
if options[:dry_run]
|
|
154
|
+
print_dry_run rest_interface.dry.create(payload)
|
|
155
|
+
return
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
rest_interface.setopts(options)
|
|
159
|
+
json_response = rest_interface.create(payload)
|
|
160
|
+
render_response(json_response, options, rest_object_key) do
|
|
161
|
+
system_id = json_response['id'] || json_response.dig(rest_object_key, 'id')
|
|
162
|
+
print_green_success "System created"
|
|
163
|
+
get([system_id.to_s] + (options[:remote] ? ['-r', options[:remote]] : [])) if system_id
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def remove(args)
|
|
168
|
+
options = {}
|
|
169
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
170
|
+
opts.banner = subcommand_usage("[system]")
|
|
171
|
+
build_standard_remove_options(opts, options)
|
|
172
|
+
opts.footer = <<-EOT
|
|
173
|
+
Delete an existing system.
|
|
174
|
+
[system] is required. This is the name or id of a system.
|
|
175
|
+
EOT
|
|
176
|
+
end
|
|
177
|
+
optparse.parse!(args)
|
|
178
|
+
verify_args!(args: args, optparse: optparse, count: 1)
|
|
179
|
+
connect(options)
|
|
180
|
+
|
|
181
|
+
system = nil
|
|
182
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
|
183
|
+
json_response = rest_interface.get(args[0].to_i)
|
|
184
|
+
system = json_response[rest_object_key] || json_response
|
|
185
|
+
else
|
|
186
|
+
system = find_by_name(rest_key, args[0])
|
|
187
|
+
end
|
|
188
|
+
return 1, "System not found for '#{args[0]}'" if system.nil?
|
|
189
|
+
|
|
190
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the system #{system['name']}?")
|
|
191
|
+
return 9, "aborted"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
if options[:dry_run]
|
|
195
|
+
print_dry_run rest_interface.dry.destroy(system['id'])
|
|
196
|
+
return
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
rest_interface.setopts(options)
|
|
200
|
+
json_response = rest_interface.destroy(system['id'])
|
|
201
|
+
render_response(json_response, options) do
|
|
202
|
+
print_green_success "System #{system['name']} removed"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def update(args)
|
|
207
|
+
options = {}
|
|
208
|
+
params = {}
|
|
209
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
|
210
|
+
opts.banner = subcommand_usage("[system] --name --description")
|
|
211
|
+
opts.on("--name NAME", String, "Updates System Name") do |val|
|
|
212
|
+
params['name'] = val.to_s
|
|
213
|
+
end
|
|
214
|
+
opts.on("--description [TEXT]", String, "Updates System Description") do |val|
|
|
215
|
+
params['description'] = val.to_s
|
|
216
|
+
end
|
|
217
|
+
build_standard_update_options(opts, options, [:find_by_name])
|
|
218
|
+
opts.footer = <<-EOT
|
|
219
|
+
Update an existing system.
|
|
220
|
+
[system] is required. This is the name or id of a system.
|
|
221
|
+
EOT
|
|
222
|
+
end
|
|
223
|
+
optparse.parse!(args)
|
|
224
|
+
verify_args!(args: args, optparse: optparse, count: 1)
|
|
225
|
+
connect(options)
|
|
226
|
+
|
|
227
|
+
system = nil
|
|
228
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
|
229
|
+
json_response = rest_interface.get(args[0].to_i)
|
|
230
|
+
system = json_response[rest_object_key] || json_response
|
|
231
|
+
else
|
|
232
|
+
system = find_by_name(rest_key, args[0])
|
|
233
|
+
end
|
|
234
|
+
return 1, "System not found for '#{args[0]}'" if system.nil?
|
|
235
|
+
|
|
236
|
+
passed_options = parse_passed_options(options)
|
|
237
|
+
params.deep_merge!(passed_options) unless passed_options.empty?
|
|
238
|
+
params.booleanize!
|
|
239
|
+
|
|
240
|
+
payload = parse_payload(options) || {rest_object_key => params}
|
|
241
|
+
if payload[rest_object_key].nil? || payload[rest_object_key].empty?
|
|
242
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
if options[:dry_run]
|
|
246
|
+
print_dry_run rest_interface.dry.update(system['id'], payload)
|
|
247
|
+
return
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
rest_interface.setopts(options)
|
|
251
|
+
json_response = rest_interface.update(system['id'], payload)
|
|
252
|
+
render_response(json_response, options, rest_object_key) do
|
|
253
|
+
print_green_success "Updated system #{system['id']}"
|
|
254
|
+
get([system['id']] + (options[:remote] ? ['-r', options[:remote]] : []))
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
def system_types_for_dropdown
|
|
259
|
+
result = @api_client.system_types.list({'max' => 100})
|
|
260
|
+
items = result ? (result['systemTypes'] || result[:systemTypes] || result['types'] || result[:types] || []) : []
|
|
261
|
+
items.map { |t| {'id' => t['id'] || t[:id], 'name' => t['name'] || t[:name], 'value' => (t['id'] || t[:id]).to_s, 'code' => t['code'] || t[:code]} }
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def system_layouts_for_dropdown(type_id = nil)
|
|
265
|
+
return [] if type_id.nil?
|
|
266
|
+
result = @api_client.system_types.list_layouts(type_id, {'max' => 100})
|
|
267
|
+
items = result ? (result['systemTypeLayouts'] || result[:systemTypeLayouts] || result['layouts'] || result[:layouts] || []) : []
|
|
268
|
+
items.map { |l| {'id' => l['id'] || l[:id], 'name' => l['name'] || l[:name], 'value' => (l['id'] || l[:id]).to_s, 'code' => l['code'] || l[:code]} }
|
|
269
|
+
end
|
|
270
|
+
end
|
|
@@ -3,6 +3,7 @@ require 'morpheus/cli/cli_command'
|
|
|
3
3
|
class Morpheus::Cli::TenantsCommand
|
|
4
4
|
include Morpheus::Cli::CliCommand
|
|
5
5
|
include Morpheus::Cli::AccountsHelper
|
|
6
|
+
include Morpheus::Cli::WhoamiHelper
|
|
6
7
|
set_command_name :tenants
|
|
7
8
|
set_command_description "View and manage tenants (accounts)."
|
|
8
9
|
register_subcommands :list, :count, :get, :add, :update, :remove
|
|
@@ -21,6 +22,7 @@ class Morpheus::Cli::TenantsCommand
|
|
|
21
22
|
@account_users_interface = @api_client.account_users
|
|
22
23
|
@accounts_interface = @api_client.accounts
|
|
23
24
|
@roles_interface = @api_client.roles
|
|
25
|
+
@whoami_interface = @api_client.whoami
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def handle(args)
|
|
@@ -286,18 +288,25 @@ EOT
|
|
|
286
288
|
[
|
|
287
289
|
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
|
288
290
|
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 2},
|
|
289
|
-
{'fieldContext' => '
|
|
290
|
-
@
|
|
291
|
+
{'fieldContext' => 'parentAccount', 'fieldName' => 'id', 'fieldLabel' => 'Parent Tenant', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
|
292
|
+
@accounts_interface.list({max:10000})['accounts'].collect {|it|
|
|
291
293
|
{"name" => (it["authority"] || it["name"]), "value" => it["id"]}
|
|
292
294
|
}
|
|
293
295
|
}, 'displayOrder' => 3},
|
|
296
|
+
{'fieldContext' => 'role', 'fieldName' => 'id', 'fieldLabel' => 'Base Role', 'type' => 'select', 'optionSource' => lambda { |api_client, api_params|
|
|
297
|
+
tenant_id = (api_params['parentAccount']['id'] rescue nil)
|
|
298
|
+
params = {max: 10000, roleType:'account', tenantId: tenant_id}
|
|
299
|
+
@roles_interface.list(nil, params)['roles'].collect {|it|
|
|
300
|
+
{"name" => (it["authority"] || it["name"]), "value" => it["id"]}
|
|
301
|
+
}
|
|
302
|
+
}, 'displayOrder' => 4},
|
|
294
303
|
{'fieldName' => 'currency', 'fieldLabel' => 'Currency', 'type' => 'text', 'defaultValue' => 'USD', 'displayOrder' => 4}
|
|
295
304
|
]
|
|
296
305
|
end
|
|
297
306
|
|
|
298
307
|
def update_account_option_types
|
|
299
308
|
list = add_account_option_types()
|
|
300
|
-
|
|
309
|
+
list = list.reject {|it| it['fieldContext'] == 'parentAccount' }
|
|
301
310
|
list.each {|it| it.delete('required') }
|
|
302
311
|
list.each {|it| it.delete('defaultValue') }
|
|
303
312
|
list
|
|
@@ -45,6 +45,7 @@ module Morpheus::Cli::AccountsHelper
|
|
|
45
45
|
"# Instances" => 'stats.instanceCount',
|
|
46
46
|
"# Users" => 'stats.userCount',
|
|
47
47
|
"Role" => lambda {|it| it['role']['authority'] rescue nil },
|
|
48
|
+
"Parent Tenant" => lambda {|it| it['parent']['name'] rescue nil },
|
|
48
49
|
"Master" => lambda {|it| format_boolean(it['master']) },
|
|
49
50
|
"Currency" => 'currency',
|
|
50
51
|
"Status" => lambda {|it|
|
|
@@ -117,6 +117,8 @@ module Morpheus::Cli::BackupsHelper
|
|
|
117
117
|
{
|
|
118
118
|
"ID" => 'id',
|
|
119
119
|
"Backup" => lambda {|it| it['backup']['name'] rescue '' },
|
|
120
|
+
"Type" => lambda {|it| format_backup_result_type_tag(it) },
|
|
121
|
+
"Location" => lambda {|it| format_backup_result_location_tag(it) },
|
|
120
122
|
"Status" => lambda {|it| format_backup_result_status(it) },
|
|
121
123
|
#"Duration" => lambda {|it| format_duration(it['startDate'], it['endDate']) },
|
|
122
124
|
"Duration" => lambda {|it| format_duration_milliseconds(it['durationMillis']) if it['durationMillis'].to_i > 0 },
|
|
@@ -168,5 +170,31 @@ module Morpheus::Cli::BackupsHelper
|
|
|
168
170
|
def format_backup_restore_status(backup_restore, return_color=cyan)
|
|
169
171
|
format_backup_result_status(backup_restore, return_color)
|
|
170
172
|
end
|
|
173
|
+
|
|
174
|
+
# format backup result type tag based on associated backup data
|
|
175
|
+
def format_backup_result_type_tag(backup_result)
|
|
176
|
+
backup = backup_result['backup'] || {}
|
|
177
|
+
if backup['cronExpression'] || (backup['schedule'] && backup['schedule']['id']) || (backup['job'] && backup['job']['id'])
|
|
178
|
+
"#{cyan}POLICY#{reset}"
|
|
179
|
+
else
|
|
180
|
+
"#{yellow}MANUAL#{reset}"
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# format backup result location tag based on storage provider
|
|
185
|
+
def format_backup_result_location_tag(backup_result)
|
|
186
|
+
backup = backup_result['backup'] || {}
|
|
187
|
+
if backup_result['storageProvider'] && backup_result['storageProvider']['id']
|
|
188
|
+
"#{green}REMOTE#{reset}"
|
|
189
|
+
elsif backup['storageProvider'] && backup['storageProvider']['id']
|
|
190
|
+
"#{green}REMOTE#{reset}"
|
|
191
|
+
elsif backup_result['backupProvider'] && backup_result['backupProvider']['id']
|
|
192
|
+
"#{green}REMOTE#{reset}"
|
|
193
|
+
elsif backup['backupProvider'] && backup['backupProvider']['id']
|
|
194
|
+
"#{green}REMOTE#{reset}"
|
|
195
|
+
else
|
|
196
|
+
"#{blue}LOCAL#{reset}"
|
|
197
|
+
end
|
|
198
|
+
end
|
|
171
199
|
|
|
172
|
-
end
|
|
200
|
+
end
|
data/lib/morpheus/cli/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: morpheus-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.0
|
|
4
|
+
version: 8.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Estes
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2026-
|
|
14
|
+
date: 2026-03-11 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: tins
|
|
@@ -381,6 +381,8 @@ files:
|
|
|
381
381
|
- lib/morpheus/api/storage_volumes_interface.rb
|
|
382
382
|
- lib/morpheus/api/subnet_types_interface.rb
|
|
383
383
|
- lib/morpheus/api/subnets_interface.rb
|
|
384
|
+
- lib/morpheus/api/system_types_interface.rb
|
|
385
|
+
- lib/morpheus/api/systems_interface.rb
|
|
384
386
|
- lib/morpheus/api/task_sets_interface.rb
|
|
385
387
|
- lib/morpheus/api/tasks_interface.rb
|
|
386
388
|
- lib/morpheus/api/usage_interface.rb
|
|
@@ -570,6 +572,7 @@ files:
|
|
|
570
572
|
- lib/morpheus/cli/commands/storage_volume_types.rb
|
|
571
573
|
- lib/morpheus/cli/commands/storage_volumes.rb
|
|
572
574
|
- lib/morpheus/cli/commands/subnets_command.rb
|
|
575
|
+
- lib/morpheus/cli/commands/systems.rb
|
|
573
576
|
- lib/morpheus/cli/commands/tasks.rb
|
|
574
577
|
- lib/morpheus/cli/commands/tee_command.rb
|
|
575
578
|
- lib/morpheus/cli/commands/tenants_command.rb
|