morpheus-cli 4.2.8 → 4.2.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/lib/morpheus/api.rb +1 -1
- data/lib/morpheus/api/activity_interface.rb +9 -0
- data/lib/morpheus/api/api_client.rb +83 -27
- data/lib/morpheus/api/apps_interface.rb +21 -0
- data/lib/morpheus/api/dashboard_interface.rb +5 -21
- data/lib/morpheus/api/instances_interface.rb +3 -10
- data/lib/morpheus/api/invoice_line_items_interface.rb +14 -0
- data/lib/morpheus/api/invoices_interface.rb +7 -12
- data/lib/morpheus/api/library_layouts_interface.rb +8 -0
- data/lib/morpheus/api/ping_interface.rb +20 -0
- data/lib/morpheus/api/projects_interface.rb +33 -0
- data/lib/morpheus/api/setup_interface.rb +19 -36
- data/lib/morpheus/api/user_settings_interface.rb +0 -6
- data/lib/morpheus/api/whoami_interface.rb +4 -8
- data/lib/morpheus/benchmarking.rb +16 -26
- data/lib/morpheus/cli.rb +10 -5
- data/lib/morpheus/cli/access_token_command.rb +5 -8
- data/lib/morpheus/cli/activity_command.rb +146 -0
- data/lib/morpheus/cli/apps.rb +312 -121
- data/lib/morpheus/cli/archives_command.rb +1 -1
- data/lib/morpheus/cli/auth_command.rb +4 -11
- data/lib/morpheus/cli/blueprints_command.rb +196 -137
- data/lib/morpheus/cli/change_password_command.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +225 -72
- data/lib/morpheus/cli/cli_registry.rb +2 -2
- data/lib/morpheus/cli/cloud_datastores_command.rb +1 -1
- data/lib/morpheus/cli/clouds.rb +5 -20
- data/lib/morpheus/cli/clusters.rb +4 -28
- data/lib/morpheus/cli/commands/standard/alias_command.rb +2 -9
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +2 -0
- data/lib/morpheus/cli/commands/standard/curl_command.rb +2 -3
- data/lib/morpheus/cli/commands/standard/history_command.rb +3 -6
- data/lib/morpheus/cli/commands/standard/man_command.rb +10 -7
- data/lib/morpheus/cli/commands/standard/ssl_verification_command.rb +10 -9
- data/lib/morpheus/cli/containers_command.rb +3 -3
- data/lib/morpheus/cli/credentials.rb +13 -16
- data/lib/morpheus/cli/error_handler.rb +18 -12
- data/lib/morpheus/cli/errors.rb +45 -0
- data/lib/morpheus/cli/execute_schedules_command.rb +1 -1
- data/lib/morpheus/cli/execution_request_command.rb +4 -4
- data/lib/morpheus/cli/groups.rb +84 -132
- data/lib/morpheus/cli/hosts.rb +6 -16
- data/lib/morpheus/cli/instances.rb +100 -183
- data/lib/morpheus/cli/invoices_command.rb +505 -71
- data/lib/morpheus/cli/library_layouts_command.rb +254 -166
- data/lib/morpheus/cli/library_option_lists_command.rb +0 -87
- data/lib/morpheus/cli/library_option_types_command.rb +0 -96
- data/lib/morpheus/cli/license.rb +3 -0
- data/lib/morpheus/cli/login.rb +17 -37
- data/lib/morpheus/cli/logout.rb +9 -5
- data/lib/morpheus/cli/mixins/accounts_helper.rb +83 -7
- data/lib/morpheus/cli/mixins/operations_helper.rb +41 -0
- data/lib/morpheus/cli/mixins/option_source_helper.rb +255 -0
- data/lib/morpheus/cli/mixins/print_helper.rb +18 -4
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +222 -13
- data/lib/morpheus/cli/mixins/remote_helper.rb +139 -0
- data/lib/morpheus/cli/monitoring_checks_command.rb +11 -3
- data/lib/morpheus/cli/network_groups_command.rb +8 -2
- data/lib/morpheus/cli/option_types.rb +1 -1
- data/lib/morpheus/cli/ping.rb +252 -0
- data/lib/morpheus/cli/price_sets_command.rb +16 -27
- data/lib/morpheus/cli/prices_command.rb +34 -27
- data/lib/morpheus/cli/processes_command.rb +81 -7
- data/lib/morpheus/cli/projects_command.rb +607 -0
- data/lib/morpheus/cli/recent_activity_command.rb +87 -65
- data/lib/morpheus/cli/remote.rb +965 -974
- data/lib/morpheus/cli/reports_command.rb +3 -15
- data/lib/morpheus/cli/roles.rb +8 -31
- data/lib/morpheus/cli/service_plans_command.rb +25 -31
- data/lib/morpheus/cli/setup.rb +392 -0
- data/lib/morpheus/cli/shell.rb +144 -56
- data/lib/morpheus/cli/subnets_command.rb +71 -11
- data/lib/morpheus/cli/tasks.rb +3 -3
- data/lib/morpheus/cli/user_sources_command.rb +4 -4
- data/lib/morpheus/cli/users.rb +135 -109
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whitelabel_settings_command.rb +7 -7
- data/lib/morpheus/cli/whoami.rb +90 -129
- data/lib/morpheus/cli/wiki_command.rb +2 -14
- data/lib/morpheus/ext/rest_client.rb +36 -0
- data/lib/morpheus/formatters.rb +42 -5
- data/lib/morpheus/rest_client.rb +0 -10
- data/lib/morpheus/terminal.rb +41 -1
- data/lib/morpheus/util.rb +24 -0
- metadata +16 -3
- data/lib/morpheus/cli/command_error.rb +0 -22
@@ -6,11 +6,14 @@ require 'morpheus/cli/mixins/library_helper'
|
|
6
6
|
|
7
7
|
class Morpheus::Cli::LibraryLayoutsCommand
|
8
8
|
include Morpheus::Cli::CliCommand
|
9
|
+
include Morpheus::Cli::ProvisioningHelper
|
10
|
+
# make sure LibraryHelper is loaded after ProvisioningHelper because it overwrites some methods like find_instance_type_by_name
|
11
|
+
# ProvisioningHelper is needed just for permissions (resourcePermissions)
|
9
12
|
include Morpheus::Cli::LibraryHelper
|
10
13
|
|
11
14
|
set_command_name :'library-layouts'
|
12
15
|
|
13
|
-
register_subcommands :list, :get, :add, :update, :remove
|
16
|
+
register_subcommands :list, :get, :add, :update, :remove, :update_permissions
|
14
17
|
|
15
18
|
def initialize()
|
16
19
|
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
@@ -108,14 +111,18 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
108
111
|
def get(args)
|
109
112
|
options = {}
|
110
113
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
111
|
-
opts.banner = subcommand_usage("[
|
112
|
-
|
114
|
+
opts.banner = subcommand_usage("[layout]")
|
115
|
+
# opts.on( nil, '--permissions', "Display permissions" ) do
|
116
|
+
# options[:show_perms] = true
|
117
|
+
# end
|
118
|
+
build_standard_get_options(opts, options)
|
119
|
+
opts.footer = <<-EOT
|
120
|
+
Get details about a layout.
|
121
|
+
[layout] is required. This is the name or id of a layout.
|
122
|
+
EOT
|
113
123
|
end
|
124
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
114
125
|
optparse.parse!(args)
|
115
|
-
if args.count < 1
|
116
|
-
puts optparse
|
117
|
-
return 1
|
118
|
-
end
|
119
126
|
connect(options)
|
120
127
|
id_list = parse_id_list(args)
|
121
128
|
return run_command_for_each_arg(id_list) do |arg|
|
@@ -124,149 +131,153 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
124
131
|
end
|
125
132
|
|
126
133
|
def _get(id, options)
|
134
|
+
exit_code, err = 0, nil
|
127
135
|
instance_type_id = nil
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
136
|
+
params = {}
|
137
|
+
params.merge!(parse_query_options(options))
|
138
|
+
@library_layouts_interface.setopts(options)
|
139
|
+
if options[:dry_run]
|
140
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
141
|
+
print_dry_run @library_layouts_interface.dry.get(instance_type_id, id.to_i, params)
|
142
|
+
else
|
143
|
+
print_dry_run @library_layouts_interface.dry.list(instance_type_id, params.merge({name:id}))
|
144
|
+
end
|
145
|
+
return
|
146
|
+
end
|
147
|
+
layout = find_layout_by_name_or_id(instance_type_id, id)
|
148
|
+
if layout.nil?
|
149
|
+
return 1
|
150
|
+
end
|
151
|
+
# skip redundant request
|
152
|
+
#json_response = @library_layouts_interface.get(instance_type_id, layout['id'])
|
153
|
+
json_response = {'instanceTypeLayout' => layout}
|
154
|
+
#layout = json_response['instanceTypeLayout']
|
155
|
+
if options[:json]
|
156
|
+
puts as_json(json_response, options, "instanceTypeLayout")
|
157
|
+
return 0
|
158
|
+
elsif options[:yaml]
|
159
|
+
puts as_yaml(json_response, options, "instanceTypeLayout")
|
160
|
+
return 0
|
161
|
+
elsif options[:csv]
|
162
|
+
puts records_as_csv([json_response['instanceTypeLayout']], options)
|
163
|
+
return 0
|
164
|
+
end
|
165
|
+
|
166
|
+
print_h1 "Layout Details"
|
167
|
+
print cyan
|
168
|
+
description_cols = {
|
169
|
+
"ID" => lambda {|it| it['id'] },
|
170
|
+
"Name" => lambda {|it| it['name'] },
|
171
|
+
"Instance Type" => lambda {|it| it['instanceType']['name'] rescue '' },
|
172
|
+
#"Code" => lambda {|it| it['code'] },
|
173
|
+
"Version" => lambda {|it| it['instanceVersion'] },
|
174
|
+
"Description" => lambda {|it| it['description'] },
|
175
|
+
"Technology" => lambda {|it| format_layout_technology(it) },
|
176
|
+
"Min Memory" => lambda {|it|
|
177
|
+
if it['memoryRequirement'].to_i != 0
|
178
|
+
(it['memoryRequirement'].to_i / (1024*1024)).to_s + " MB"
|
133
179
|
else
|
134
|
-
|
180
|
+
""
|
135
181
|
end
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
#
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
182
|
+
},
|
183
|
+
"Workflow" => lambda {|it|
|
184
|
+
if it['taskSets']
|
185
|
+
it['taskSets'][0]['name'] rescue ""
|
186
|
+
else
|
187
|
+
""
|
188
|
+
end
|
189
|
+
},
|
190
|
+
# "Category" => lambda {|it| it['category'].to_s.capitalize },
|
191
|
+
# # "Logo" => lambda {|it| it['logo'].to_s },
|
192
|
+
# "Visiblity" => lambda {|it| it['visibility'].to_s.capitalize },
|
193
|
+
# "Environment Prefix" => lambda {|it| it['environmentPrefix'] },
|
194
|
+
# "Enable Settings" => lambda {|it| format_boolean it['hasSettings'] },
|
195
|
+
# "Enable Scaling" => lambda {|it| format_boolean it['hasAutoScale'] },
|
196
|
+
# "Supports Deployments" => lambda {|it| format_boolean it['hasDeployment'] },
|
197
|
+
# "Featured" => lambda {|it| format_boolean it['featured'] },
|
198
|
+
# "Owner" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
199
|
+
# "Active" => lambda {|it| format_boolean it['active'] },
|
200
|
+
# "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
201
|
+
# "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
202
|
+
}
|
203
|
+
print_description_list(description_cols, layout)
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
layout_evars = layout['environmentVariables']
|
208
|
+
if layout_evars && layout_evars.size > 0
|
209
|
+
print_h2 "Environment Variables"
|
210
|
+
evar_columns = [
|
211
|
+
{"NAME" => lambda {|it| it['name'] } },
|
212
|
+
{"VALUE" => lambda {|it| it['defaultValue'] } },
|
213
|
+
{"TYPE" => lambda {|it| it['valueType'].to_s.capitalize } },
|
214
|
+
{"EXPORT" => lambda {|it| format_boolean it['export'] } },
|
215
|
+
{"MASKED" => lambda {|it| format_boolean it['mask'] } },
|
216
|
+
]
|
217
|
+
print as_pretty_table(layout_evars, evar_columns)
|
218
|
+
else
|
219
|
+
# print yellow,"No environment variables found for this instance type.","\n",reset
|
220
|
+
end
|
156
221
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
"
|
162
|
-
"
|
163
|
-
|
164
|
-
"
|
165
|
-
"
|
166
|
-
"
|
167
|
-
"
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
},
|
174
|
-
"Workflow" => lambda {|it|
|
175
|
-
if it['taskSets']
|
176
|
-
it['taskSets'][0]['name'] rescue ""
|
177
|
-
else
|
178
|
-
""
|
179
|
-
end
|
180
|
-
},
|
181
|
-
# "Category" => lambda {|it| it['category'].to_s.capitalize },
|
182
|
-
# # "Logo" => lambda {|it| it['logo'].to_s },
|
183
|
-
# "Visiblity" => lambda {|it| it['visibility'].to_s.capitalize },
|
184
|
-
# "Environment Prefix" => lambda {|it| it['environmentPrefix'] },
|
185
|
-
# "Enable Settings" => lambda {|it| format_boolean it['hasSettings'] },
|
186
|
-
# "Enable Scaling" => lambda {|it| format_boolean it['hasAutoScale'] },
|
187
|
-
# "Supports Deployments" => lambda {|it| format_boolean it['hasDeployment'] },
|
188
|
-
# "Featured" => lambda {|it| format_boolean it['featured'] },
|
189
|
-
# "Owner" => lambda {|it| it['account'] ? it['account']['name'] : '' },
|
190
|
-
# "Active" => lambda {|it| format_boolean it['active'] },
|
191
|
-
# "Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
192
|
-
# "Updated" => lambda {|it| format_local_dt(it['lastUpdated']) }
|
193
|
-
}
|
194
|
-
print_description_list(description_cols, layout)
|
222
|
+
layout_option_types = layout['optionTypes']
|
223
|
+
if layout_option_types && layout_option_types.size > 0
|
224
|
+
print_h2 "Option Types"
|
225
|
+
columns = [
|
226
|
+
{"ID" => lambda {|it| it['id'] } },
|
227
|
+
{"NAME" => lambda {|it| it['name'] } },
|
228
|
+
{"TYPE" => lambda {|it| it['type'] } },
|
229
|
+
{"FIELD NAME" => lambda {|it| it['fieldName'] } },
|
230
|
+
{"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
|
231
|
+
{"DEFAULT" => lambda {|it| it['defaultValue'] } },
|
232
|
+
{"REQUIRED" => lambda {|it| format_boolean it['required'] } },
|
233
|
+
]
|
234
|
+
print as_pretty_table(layout_option_types, columns)
|
235
|
+
else
|
236
|
+
# print yellow,"No option types found for this layout.","\n",reset
|
237
|
+
end
|
195
238
|
|
196
|
-
|
239
|
+
layout_node_types = layout['containerTypes']
|
240
|
+
if layout_node_types && layout_node_types.size > 0
|
241
|
+
print_h2 "Node Types"
|
242
|
+
# match UI sorting [version desc, name asc]
|
243
|
+
# or use something simpler like one of these
|
244
|
+
layout_node_types = layout_node_types.sort { |a,b| a['name'] <=> b['name'] }
|
245
|
+
# layout_node_types = layout_node_types.sort { |a,b| a['sortOrder'] <=> b['sortOrder'] }
|
246
|
+
node_type_columns = [
|
247
|
+
{"ID" => lambda {|it| it['id'] } },
|
248
|
+
{"NAME" => lambda {|it| it['name'] } },
|
249
|
+
{"SHORT NAME" => lambda {|it| it['shortName'] } },
|
250
|
+
{"VERSION" => lambda {|it| it['containerVersion'] } },
|
251
|
+
{"TECHNOLOGY" => lambda {|it| it['provisionType'] ? it['provisionType']['name'] : '' } },
|
252
|
+
{"CATEGORY" => lambda {|it| it['category'] } },
|
253
|
+
]
|
254
|
+
print as_pretty_table(layout_node_types, node_type_columns)
|
255
|
+
else
|
256
|
+
# print yellow,"No node types for this layout.","\n",reset
|
257
|
+
end
|
197
258
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
end
|
212
|
-
|
213
|
-
layout_option_types = layout['optionTypes']
|
214
|
-
if layout_option_types && layout_option_types.size > 0
|
215
|
-
print_h2 "Option Types"
|
216
|
-
columns = [
|
217
|
-
{"ID" => lambda {|it| it['id'] } },
|
218
|
-
{"NAME" => lambda {|it| it['name'] } },
|
219
|
-
{"TYPE" => lambda {|it| it['type'] } },
|
220
|
-
{"FIELD NAME" => lambda {|it| it['fieldName'] } },
|
221
|
-
{"FIELD LABEL" => lambda {|it| it['fieldLabel'] } },
|
222
|
-
{"DEFAULT" => lambda {|it| it['defaultValue'] } },
|
223
|
-
{"REQUIRED" => lambda {|it| format_boolean it['required'] } },
|
224
|
-
]
|
225
|
-
print as_pretty_table(layout_option_types, columns)
|
226
|
-
else
|
227
|
-
# print yellow,"No option types found for this layout.","\n",reset
|
228
|
-
end
|
229
|
-
|
230
|
-
layout_node_types = layout['containerTypes']
|
231
|
-
if layout_node_types && layout_node_types.size > 0
|
232
|
-
print_h2 "Node Types"
|
233
|
-
# match UI sorting [version desc, name asc]
|
234
|
-
# or use something simpler like one of these
|
235
|
-
layout_node_types = layout_node_types.sort { |a,b| a['name'] <=> b['name'] }
|
236
|
-
# layout_node_types = layout_node_types.sort { |a,b| a['sortOrder'] <=> b['sortOrder'] }
|
237
|
-
node_type_columns = [
|
238
|
-
{"ID" => lambda {|it| it['id'] } },
|
239
|
-
{"NAME" => lambda {|it| it['name'] } },
|
240
|
-
{"SHORT NAME" => lambda {|it| it['shortName'] } },
|
241
|
-
{"VERSION" => lambda {|it| it['containerVersion'] } },
|
242
|
-
{"TECHNOLOGY" => lambda {|it| it['provisionType'] ? it['provisionType']['name'] : '' } },
|
243
|
-
{"CATEGORY" => lambda {|it| it['category'] } },
|
244
|
-
]
|
245
|
-
print as_pretty_table(layout_node_types, node_type_columns)
|
246
|
-
else
|
247
|
-
# print yellow,"No node types for this layout.","\n",reset
|
248
|
-
end
|
249
|
-
|
250
|
-
layout_spec_templates = layout['specTemplates']
|
251
|
-
if layout_spec_templates && layout_spec_templates.size > 0
|
252
|
-
print_h2 "Spec Templates"
|
253
|
-
layout_spec_templates = layout_spec_templates.sort { |a,b| a['name'] <=> b['name'] }
|
254
|
-
spec_template_columns = [
|
255
|
-
{"ID" => lambda {|it| it['id'] } },
|
256
|
-
{"NAME" => lambda {|it| it['name'] } },
|
257
|
-
{"TYPE" => lambda {|it| it['type']['name'] rescue '' } }
|
258
|
-
]
|
259
|
-
print as_pretty_table(layout_spec_templates, spec_template_columns)
|
260
|
-
else
|
261
|
-
# print yellow,"No spec templates for this layout.","\n",reset
|
262
|
-
end
|
259
|
+
layout_spec_templates = layout['specTemplates']
|
260
|
+
if layout_spec_templates && layout_spec_templates.size > 0
|
261
|
+
print_h2 "Spec Templates"
|
262
|
+
layout_spec_templates = layout_spec_templates.sort { |a,b| a['name'] <=> b['name'] }
|
263
|
+
spec_template_columns = [
|
264
|
+
{"ID" => lambda {|it| it['id'] } },
|
265
|
+
{"NAME" => lambda {|it| it['name'] } },
|
266
|
+
{"TYPE" => lambda {|it| it['type']['name'] rescue '' } }
|
267
|
+
]
|
268
|
+
print as_pretty_table(layout_spec_templates, spec_template_columns)
|
269
|
+
else
|
270
|
+
# print yellow,"No spec templates for this layout.","\n",reset
|
271
|
+
end
|
263
272
|
|
264
|
-
print reset,"\n"
|
265
273
|
|
266
|
-
|
267
|
-
|
268
|
-
|
274
|
+
if options[:show_perms] || (layout['permissions'] && !layout['permissions'].empty?)
|
275
|
+
print_permissions(layout['permissions'], layout_permission_excludes)
|
276
|
+
print reset
|
277
|
+
else
|
278
|
+
print reset,"\n"
|
269
279
|
end
|
280
|
+
return exit_code, err
|
270
281
|
end
|
271
282
|
|
272
283
|
def add(args)
|
@@ -327,9 +338,12 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
327
338
|
params['specTemplates'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
328
339
|
end
|
329
340
|
end
|
330
|
-
|
331
|
-
opts
|
332
|
-
|
341
|
+
add_perms_options(opts, options, layout_permission_excludes)
|
342
|
+
build_standard_add_options(opts, options)
|
343
|
+
opts.footer = <<-EOT
|
344
|
+
Create a new layout.
|
345
|
+
[instance-type] is required and can be passed as --instance-type instead.
|
346
|
+
EOT
|
333
347
|
end
|
334
348
|
optparse.parse!(args)
|
335
349
|
if args.count > 1
|
@@ -442,6 +456,15 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
442
456
|
|
443
457
|
payload = {'instanceTypeLayout' => params}
|
444
458
|
|
459
|
+
# Resource Permissions (Groups only for layouts)
|
460
|
+
perms = prompt_permissions(options.merge({}), layout_permission_excludes)
|
461
|
+
perms_payload = {}
|
462
|
+
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].empty?
|
463
|
+
#perms_payload['tenantPermissions'] = perms['tenantPermissions'] if !perms['tenantPermissions'].nil?
|
464
|
+
|
465
|
+
payload['instanceTypeLayout']['permissions'] = perms_payload
|
466
|
+
payload['instanceTypeLayout']['visibility'] = perms['resourcePool']['visibility'] if !perms['resourcePool'].nil? && !perms['resourcePool']['visibility'].nil?
|
467
|
+
|
445
468
|
end
|
446
469
|
@library_layouts_interface.setopts(options)
|
447
470
|
if options[:dry_run]
|
@@ -456,7 +479,7 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
456
479
|
return
|
457
480
|
end
|
458
481
|
|
459
|
-
print_green_success "Added
|
482
|
+
print_green_success "Added layout #{params['name']}"
|
460
483
|
|
461
484
|
#get([json_response['instanceTypeLayout']['id']])
|
462
485
|
|
@@ -472,7 +495,7 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
472
495
|
instance_type_id = nil
|
473
496
|
evars = nil
|
474
497
|
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
475
|
-
opts.banner = subcommand_usage("[
|
498
|
+
opts.banner = subcommand_usage("[layout] [options]")
|
476
499
|
opts.on('--name VALUE', String, "Name for this layout") do |val|
|
477
500
|
params['name'] = val
|
478
501
|
end
|
@@ -521,16 +544,18 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
521
544
|
params['specTemplates'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
522
545
|
end
|
523
546
|
end
|
524
|
-
|
525
|
-
opts
|
547
|
+
add_perms_options(opts, options, layout_permission_excludes)
|
548
|
+
build_standard_update_options(opts, options)
|
549
|
+
opts.footer = <<-EOT
|
550
|
+
Update a layout.
|
551
|
+
[layout] is required. This is the name or id of a layout.
|
552
|
+
EOT
|
526
553
|
end
|
527
554
|
optparse.parse!(args)
|
528
|
-
|
529
|
-
puts optparse
|
530
|
-
exit 1
|
531
|
-
end
|
555
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
532
556
|
connect(options)
|
533
|
-
|
557
|
+
exit_code, err = 0, nil
|
558
|
+
|
534
559
|
layout = find_layout_by_name_or_id(nil, args[0])
|
535
560
|
exit 1 if layout.nil?
|
536
561
|
payload = nil
|
@@ -576,6 +601,16 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
576
601
|
end
|
577
602
|
end
|
578
603
|
|
604
|
+
# perms
|
605
|
+
if options[:groupAccessAll] != nil || options[:groupAccessList]
|
606
|
+
perms = prompt_permissions(options.merge({no_prompt:true}), layout_permission_excludes)
|
607
|
+
perms_payload = {}
|
608
|
+
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].empty?
|
609
|
+
params.deep_merge!({'permissions' => perms_payload}) if !perms_payload.empty?
|
610
|
+
end
|
611
|
+
|
612
|
+
params['visibility'] = options[:visibility] if !options[:visibility].nil?
|
613
|
+
|
579
614
|
if params.empty?
|
580
615
|
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
581
616
|
end
|
@@ -596,12 +631,61 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
596
631
|
return
|
597
632
|
end
|
598
633
|
|
599
|
-
print_green_success "Updated
|
634
|
+
print_green_success "Updated layout #{params['name'] || layout['name']}"
|
600
635
|
#list([])
|
601
|
-
|
602
|
-
|
603
|
-
|
636
|
+
return exit_code, err
|
637
|
+
end
|
638
|
+
|
639
|
+
def update_permissions(args)
|
640
|
+
options = {}
|
641
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
642
|
+
opts.banner = subcommand_usage( "[layout]")
|
643
|
+
add_perms_options(opts, options, layout_permission_excludes)
|
644
|
+
build_standard_update_options(opts, options)
|
645
|
+
opts.footer = <<-EOT
|
646
|
+
Update layout permissions.
|
647
|
+
[layout] is required. This is the name or id of a layout.
|
648
|
+
EOT
|
649
|
+
end
|
650
|
+
optparse.parse!(args)
|
651
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
652
|
+
connect(options)
|
653
|
+
exit_code, err = 0, nil
|
654
|
+
# if !is_master_account
|
655
|
+
# print_red_alert "Permissions only available for master account"
|
656
|
+
# return 1
|
657
|
+
# end
|
658
|
+
layout = find_layout_by_name_or_id(nil, args[0])
|
659
|
+
return 1, "layout not found for #{args[0]}" if layout.nil?
|
660
|
+
payload = {}
|
661
|
+
if options[:payload]
|
662
|
+
payload = options[:payload]
|
663
|
+
payload.deep_merge!(parse_passed_options(options))
|
664
|
+
else
|
665
|
+
payload.deep_merge!(parse_passed_options(options))
|
666
|
+
|
667
|
+
perms = prompt_permissions(options.merge({}), layout_permission_excludes)
|
668
|
+
perms_payload = {}
|
669
|
+
perms_payload['resourcePermissions'] = perms['resourcePermissions'] if !perms['resourcePermissions'].empty?
|
670
|
+
payload.deep_merge!({'permissions' => perms_payload}) if !perms_payload.empty?
|
671
|
+
end
|
672
|
+
|
673
|
+
@library_layouts_interface.setopts(options)
|
674
|
+
if options[:dry_run]
|
675
|
+
print_dry_run @library_layouts_interface.dry.update_permissions(layout['id'], payload)
|
676
|
+
return
|
604
677
|
end
|
678
|
+
json_response = @library_layouts_interface.update_permissions(layout['id'], payload)
|
679
|
+
render_response(json_response, options, 'instanceTypeLayout') do
|
680
|
+
# note: this api does not return 400 when it fails?
|
681
|
+
if json_response['success']
|
682
|
+
print_green_success "Updated layout permissions"
|
683
|
+
else
|
684
|
+
print_rest_errors(json_response, options)
|
685
|
+
exit_code, err = 3, (json_response['msg'] || "api did not return success:true")
|
686
|
+
end
|
687
|
+
end
|
688
|
+
return exit_code, err
|
605
689
|
end
|
606
690
|
|
607
691
|
def remove(args)
|
@@ -637,7 +721,7 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
637
721
|
return
|
638
722
|
end
|
639
723
|
|
640
|
-
print_green_success "Removed
|
724
|
+
print_green_success "Removed layout #{layout['name']}"
|
641
725
|
#list([])
|
642
726
|
rescue RestClient::Exception => e
|
643
727
|
print_rest_exception(e, options)
|
@@ -647,29 +731,30 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
647
731
|
|
648
732
|
private
|
649
733
|
|
650
|
-
def find_layout_by_name_or_id(instance_type_id, val)
|
734
|
+
def find_layout_by_name_or_id(instance_type_id, val, params={})
|
651
735
|
if val.to_s =~ /\A\d{1,}\Z/
|
652
|
-
return find_layout_by_id(instance_type_id, val)
|
736
|
+
return find_layout_by_id(instance_type_id, val, params)
|
653
737
|
else
|
654
|
-
return find_layout_by_name(instance_type_id, val)
|
738
|
+
return find_layout_by_name(instance_type_id, val, params)
|
655
739
|
end
|
656
740
|
end
|
657
741
|
|
658
|
-
def find_layout_by_id(instance_type_id, id)
|
742
|
+
def find_layout_by_id(instance_type_id, id, params={})
|
659
743
|
begin
|
660
|
-
json_response = @library_layouts_interface.get(instance_type_id, id.to_i)
|
744
|
+
json_response = @library_layouts_interface.get(instance_type_id, id.to_i, params)
|
661
745
|
return json_response['instanceTypeLayout']
|
662
746
|
rescue RestClient::Exception => e
|
663
747
|
if e.response && e.response.code == 404
|
664
|
-
|
748
|
+
print_rest_exception(e)
|
749
|
+
#print_red_alert "Layout not found by id #{id}"
|
665
750
|
else
|
666
751
|
raise e
|
667
752
|
end
|
668
753
|
end
|
669
754
|
end
|
670
755
|
|
671
|
-
def find_layout_by_name(instance_type_id, name)
|
672
|
-
layouts = @library_layouts_interface.list(instance_type_id, {name: name.to_s})['instanceTypeLayouts']
|
756
|
+
def find_layout_by_name(instance_type_id, name, params={})
|
757
|
+
layouts = @library_layouts_interface.list(instance_type_id, params.merge({name: name.to_s}))['instanceTypeLayouts']
|
673
758
|
if layouts.empty?
|
674
759
|
print_red_alert "Layout not found by name #{name}"
|
675
760
|
return nil
|
@@ -712,4 +797,7 @@ class Morpheus::Cli::LibraryLayoutsCommand
|
|
712
797
|
val.to_s # .capitalize
|
713
798
|
end
|
714
799
|
|
800
|
+
def layout_permission_excludes
|
801
|
+
['plans', 'groupDefaults', 'visibility', 'tenants']
|
802
|
+
end
|
715
803
|
end
|