morpheus-cli 3.4.1.10 → 3.5.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.
@@ -11,7 +11,7 @@ class Morpheus::Cli::Echo
11
11
  set_command_hidden
12
12
 
13
13
  unless defined?(DEFAULT_VARIABLE_MAP)
14
- DEFAULT_VARIABLE_MAP = {'%cyan' => Term::ANSIColor.cyan, '%magenta' => Term::ANSIColor.magenta, '%red' => Term::ANSIColor.red, '%green' => Term::ANSIColor.green, '%yellow' => Term::ANSIColor.yellow, '%dark' => Term::ANSIColor.dark, '%reset' => Term::ANSIColor.reset}
14
+ DEFAULT_VARIABLE_MAP = {'%cyan' => Term::ANSIColor.cyan, '%magenta' => Term::ANSIColor.magenta, '%red' => Term::ANSIColor.red, '%green' => Term::ANSIColor.green, '%yellow' => Term::ANSIColor.yellow, '%white' => Term::ANSIColor.white, '%dark' => Term::ANSIColor.dark, '%reset' => Term::ANSIColor.reset}
15
15
  end
16
16
 
17
17
  def self.variable_map
@@ -129,25 +129,38 @@ class Morpheus::Cli::LibraryOptionListsCommand
129
129
  # print_h2 "Initial Dataset"
130
130
  # print bright_black,"#{option_type_list['initialDataset']}","\n",reset
131
131
  else
132
- print_description_list({
132
+ option_list_columns = {
133
133
  "ID" => 'id',
134
134
  "Name" => 'name',
135
135
  "Description" => 'description',
136
136
  "Type" => lambda {|it| it['type'].to_s.capitalize },
137
137
  "Source URL" => 'sourceUrl',
138
+ "Real Time" => lambda {|it| format_boolean it['realTime'] },
138
139
  "Ignore SSL Errors" => lambda {|it| format_boolean it['ignoreSSLErrors'] },
139
- "Source Method" => lambda {|it| it['sourceMethod'].to_s.upcase },
140
- }, option_type_list)
140
+ "Source Method" => lambda {|it| it['sourceMethod'].to_s.upcase }
141
+ }
142
+ source_headers = []
143
+ if option_type_list['config'] && option_type_list['config']['sourceHeaders']
144
+ source_headers = option_type_list['config']['sourceHeaders'].collect do |header|
145
+ {name: header['name'], value: header['value'], masked: format_boolean(header['masked'])}
146
+ end
147
+ #option_list_columns["Source Headers"] = lambda {|it| source_headers.collect {|it| "#{it[:name]} #{it[:value]}"}.join("\n") }
148
+ end
149
+ print_description_list(option_list_columns, option_type_list)
150
+ if source_headers && !source_headers.empty?
151
+ print cyan
152
+ print_h2 "Source Headers"
153
+ print as_pretty_table(source_headers, [:name, :value, :masked])
154
+ end
141
155
  if !option_type_list['initialDataset'].empty?
142
156
  print_h2 "Initial Dataset"
143
- print bright_black," #{option_type_list['initialDataset']}","\n",reset
157
+ print bright_black,"#{option_type_list['initialDataset']}","\n",reset
144
158
  end
145
159
  if !option_type_list['translationScript'].empty?
146
160
  print_h2 "Translation Script"
147
- print bright_black," #{option_type_list['translationScript']}","\n",reset
161
+ print bright_black,"#{option_type_list['translationScript']}","\n",reset
148
162
  end
149
163
  end
150
-
151
164
  print_h2 "List Items"
152
165
  if option_type_list['listItems']
153
166
  # puts "\tNAME\tVALUE"
@@ -181,7 +194,7 @@ class Morpheus::Cli::LibraryOptionListsCommand
181
194
  # options[:options]['type'] = val
182
195
  end
183
196
  build_option_type_options(opts, options, new_option_type_list_option_types())
184
- build_common_options(opts, options, [:options, :json, :dry_run, :remote])
197
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
185
198
  end
186
199
  optparse.parse!(args)
187
200
 
@@ -192,13 +205,31 @@ class Morpheus::Cli::LibraryOptionListsCommand
192
205
 
193
206
  connect(options)
194
207
  begin
195
- params = Morpheus::Cli::OptionTypes.prompt(new_option_type_list_option_types(list_type), options[:options], @api_client, options[:params])
196
- if params.key?('required')
197
- params['required'] = ['on','true'].include?(params['required'].to_s)
208
+ payload = nil
209
+ if options[:payload]
210
+ payload = options[:payload]
211
+ # support -O OPTION switch on top of --payload
212
+ if options[:options]
213
+ payload['optionTypeList'] ||= {}
214
+ payload['optionTypeList'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
215
+ end
216
+ else
217
+ params = Morpheus::Cli::OptionTypes.prompt(new_option_type_list_option_types(list_type), options[:options], @api_client, options[:params])
218
+ params['type'] = list_type
219
+ if params['type'] == 'rest'
220
+ # prompt for Source Headers
221
+ source_headers = prompt_source_headers(options)
222
+ if !source_headers.empty?
223
+ params['config'] ||= {}
224
+ params['config']['sourceHeaders'] = source_headers
225
+ end
226
+ end
227
+ if params.key?('required')
228
+ params['required'] = ['on','true'].include?(params['required'].to_s)
229
+ end
230
+ list_payload = params
231
+ payload = {'optionTypeList' => list_payload}
198
232
  end
199
- params['type'] = list_type
200
- list_payload = params
201
- payload = {'optionTypeList' => list_payload}
202
233
  if options[:dry_run]
203
234
  print_dry_run @option_type_lists_interface.dry.create(payload)
204
235
  return
@@ -227,7 +258,7 @@ class Morpheus::Cli::LibraryOptionListsCommand
227
258
  optparse = Morpheus::Cli::OptionParser.new do |opts|
228
259
  opts.banner = subcommand_usage("[name] [options]")
229
260
  build_option_type_options(opts, options, update_option_type_list_option_types())
230
- build_common_options(opts, options, [:options, :json, :dry_run, :remote])
261
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
231
262
  end
232
263
  optparse.parse!(args)
233
264
  connect(options)
@@ -235,20 +266,39 @@ class Morpheus::Cli::LibraryOptionListsCommand
235
266
  option_type_list = find_option_type_list_by_name_or_id(args[0])
236
267
  exit 1 if option_type_list.nil?
237
268
 
238
- list_type = option_type_list['type']
239
- prompt_options = update_option_type_list_option_types(list_type)
240
- #params = options[:options] || {}
241
- params = Morpheus::Cli::OptionTypes.no_prompt(prompt_options, options[:options], @api_client, options[:params])
242
- if params.empty?
243
- print_red_alert "Specify atleast one option to update"
244
- puts optparse
245
- exit 1
246
- end
247
- if params.key?('required')
248
- params['required'] = ['on','true'].include?(params['required'].to_s)
269
+ payload = nil
270
+ if options[:payload]
271
+ payload = options[:payload]
272
+ # support -O OPTION switch on top of --payload
273
+ if options[:options]
274
+ payload['optionTypeList'] ||= {}
275
+ payload['optionTypeList'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) })
276
+ end
277
+ else
278
+ list_type = option_type_list['type']
279
+ prompt_options = update_option_type_list_option_types(list_type)
280
+ #params = options[:options] || {}
281
+ params = Morpheus::Cli::OptionTypes.no_prompt(prompt_options, options[:options], @api_client, options[:params])
282
+ if list_type == 'rest'
283
+ # parse Source Headers
284
+ source_headers = prompt_source_headers(options.merge({no_prompt: true}))
285
+ if !source_headers.empty?
286
+ #params['config'] ||= option_type_list['config'] || {}
287
+ params['config'] ||= {}
288
+ params['config']['sourceHeaders'] = source_headers
289
+ end
290
+ end
291
+ if params.empty?
292
+ print_red_alert "Specify atleast one option to update"
293
+ puts optparse
294
+ exit 1
295
+ end
296
+ if params.key?('required')
297
+ params['required'] = ['on','true'].include?(params['required'].to_s)
298
+ end
299
+ list_payload = params
300
+ payload = {'optionTypeList' => list_payload}
249
301
  end
250
- list_payload = params
251
- payload = {optionTypeList: list_payload}
252
302
  if options[:dry_run]
253
303
  print_dry_run @option_type_lists_interface.dry.update(option_type_list['id'], payload)
254
304
  return
@@ -446,9 +496,10 @@ class Morpheus::Cli::LibraryOptionListsCommand
446
496
  #{'fieldName' => 'type', 'fieldLabel' => 'Type', 'type' => 'select', 'selectOptions' => get_available_option_list_types, 'defaultValue' => 'rest', 'required' => true, 'displayOrder' => 3},
447
497
  {'fieldName' => 'sourceUrl', 'fieldLabel' => 'Source Url', 'type' => 'text', 'required' => true, 'description' => "A REST URL can be used to fetch list data and is cached in the appliance database.", 'displayOrder' => 4},
448
498
  {'fieldName' => 'ignoreSSLErrors', 'fieldLabel' => 'Ignore SSL Errors', 'type' => 'checkbox', 'defaultValue' => 'off', 'displayOrder' => 5},
449
- {'fieldName' => 'sourceMethod', 'fieldLabel' => 'Source Method', 'type' => 'select', 'selectOptions' => [{'name' => 'GET', 'value' => 'GET'}, {'name' => 'POST', 'value' => 'POST'}], 'defaultValue' => 'GET', 'required' => true, 'displayOrder' => 6},
450
- {'fieldName' => 'initialDataset', 'fieldLabel' => 'Initial Dataset', 'type' => 'code-editor', 'description' => "Create an initial json dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'. However, if there is a translation script, that will also be passed through.", 'displayOrder' => 7},
451
- {'fieldName' => 'translationScript', 'fieldLabel' => 'Translation Script', 'type' => 'code-editor', 'description' => "Create a js script to translate the result data object into an Array containing objects with properties name, and value. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 8},
499
+ {'fieldName' => 'realTime', 'fieldLabel' => 'Real Time', 'type' => 'checkbox', 'defaultValue' => 'off', 'displayOrder' => 6},
500
+ {'fieldName' => 'sourceMethod', 'fieldLabel' => 'Source Method', 'type' => 'select', 'selectOptions' => [{'name' => 'GET', 'value' => 'GET'}, {'name' => 'POST', 'value' => 'POST'}], 'defaultValue' => 'GET', 'required' => true, 'displayOrder' => 7},
501
+ {'fieldName' => 'initialDataset', 'fieldLabel' => 'Initial Dataset', 'type' => 'code-editor', 'description' => "Create an initial json dataset to be used as the collection for this option list. It should be a list containing objects with properties 'name', and 'value'. However, if there is a translation script, that will also be passed through.", 'displayOrder' => 8},
502
+ {'fieldName' => 'translationScript', 'fieldLabel' => 'Translation Script', 'type' => 'code-editor', 'description' => "Create a js script to translate the result data object into an Array containing objects with properties name, and value. The input data is provided as data and the result should be put on the global variable results.", 'displayOrder' => 9},
452
503
  ]
453
504
  elsif list_type.to_s.downcase == 'manual'
454
505
  [
@@ -473,4 +524,32 @@ class Morpheus::Cli::LibraryOptionListsCommand
473
524
  list
474
525
  end
475
526
 
527
+ # returns array of header objects {name: "Auth", value: "somevalue", masked: false}
528
+ def prompt_source_headers(options={})
529
+ #puts "Source Headers:"
530
+ no_prompt = (options[:no_prompt] || (options[:options] && options[:options][:no_prompt]))
531
+ source_headers = []
532
+ source_header_index = 0
533
+ has_another_source_header = options[:options] && options[:options]["sourceHeader#{source_header_index}"]
534
+ add_another_source_header = has_another_source_header || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add a Source Header?", {default: false}))
535
+ while add_another_source_header do
536
+ field_context = "sourceHeader#{source_header_index}"
537
+ source_header = {}
538
+ source_header['id'] = nil
539
+ source_header_label = source_header_index == 0 ? "Header" : "Header [#{source_header_index+1}]"
540
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'name', 'type' => 'text', 'fieldLabel' => "#{source_header_label} Name", 'required' => true, 'description' => 'HTTP Header Name.', 'defaultValue' => source_header['name']}], options[:options])
541
+ source_header['name'] = v_prompt[field_context]['name']
542
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'value', 'type' => 'text', 'fieldLabel' => "#{source_header_label} Value", 'required' => true, 'description' => 'HTTP Header Value', 'defaultValue' => source_header['value']}], options[:options])
543
+ source_header['value'] = v_prompt[field_context]['value']
544
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldContext' => field_context, 'fieldName' => 'masked', 'type' => 'checkbox', 'fieldLabel' => "#{source_header_label} Masked", 'required' => true, 'description' => 'Header value is secret and should not be displayed', 'defaultValue' => source_header['masked'] ? 'yes' : 'no'}], options[:options])
545
+ source_header['masked'] = v_prompt[field_context]['masked'] if !v_prompt[field_context]['masked'].nil?
546
+ source_headers << source_header
547
+ source_header_index += 1
548
+ has_another_source_header = options[:options] && options[:options]["sourceHeader#{source_header_index}"]
549
+ add_another_source_header = has_another_source_header || (!no_prompt && Morpheus::Cli::OptionTypes.confirm("Add another Source Header?", {default: false}))
550
+ end
551
+
552
+ return source_headers
553
+ end
554
+
476
555
  end
@@ -6,10 +6,12 @@ require 'filesize'
6
6
  require 'table_print'
7
7
  require 'morpheus/cli/cli_command'
8
8
  require 'morpheus/cli/mixins/infrastructure_helper'
9
+ require 'morpheus/cli/mixins/accounts_helper'
9
10
 
10
11
  class Morpheus::Cli::PoliciesCommand
11
12
  include Morpheus::Cli::CliCommand
12
13
  include Morpheus::Cli::InfrastructureHelper
14
+ include Morpheus::Cli::AccountsHelper
13
15
 
14
16
  set_command_name :policies
15
17
 
@@ -31,6 +33,7 @@ class Morpheus::Cli::PoliciesCommand
31
33
  @cloud_policies_interface = @api_client.cloud_policies
32
34
  @clouds_interface = @api_client.clouds
33
35
  @groups_interface = @api_client.groups
36
+ @users_interface = @api_client.users
34
37
  @active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
35
38
  end
36
39
 
@@ -49,22 +52,32 @@ class Morpheus::Cli::PoliciesCommand
49
52
  opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
50
53
  options[:cloud] = val
51
54
  end
52
- opts.on( '-G', '--global', "Exclude policies scoped to a group or cloud" ) do
55
+ opts.on( '-u', '--user USER', "Username or ID" ) do |val|
56
+ options[:user] = val
57
+ end
58
+ opts.on( '-G', '--global', "Global policies only" ) do
53
59
  params[:global] = true
54
60
  end
55
- build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
61
+ build_common_options(opts, options, [:list, :query, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
56
62
  opts.footer = "List policies."
57
63
  end
58
64
  optparse.parse!(args)
59
65
  connect(options)
60
66
  begin
61
- group, cloud = nil, nil
67
+ group, cloud, user = nil, nil, nil
62
68
  if options[:group]
63
69
  group = find_group_by_name_or_id(options[:group])
64
70
  elsif options[:cloud]
65
71
  cloud = find_cloud_by_name_or_id(options[:cloud])
72
+ elsif options[:user]
73
+ user = find_user_by_username_or_id(nil, options[:user])
74
+ return 1 if user.nil?
66
75
  end
67
76
  params.merge!(parse_list_options(options))
77
+ if user
78
+ params['refType'] = 'User'
79
+ params['refId'] = user['id']
80
+ end
68
81
  if options[:dry_run]
69
82
  if group
70
83
  print_dry_run @group_policies_interface.dry.list(group['id'], params)
@@ -72,6 +85,10 @@ class Morpheus::Cli::PoliciesCommand
72
85
  print_dry_run @cloud_policies_interface.dry.list(cloud['id'], params)
73
86
  else
74
87
  # global
88
+ if user
89
+ params['refType'] = 'User'
90
+ params['refId'] = user['id']
91
+ end
75
92
  print_dry_run @policies_interface.dry.list(params)
76
93
  end
77
94
  return 0
@@ -103,6 +120,9 @@ class Morpheus::Cli::PoliciesCommand
103
120
  if cloud
104
121
  subtitles << "Cloud: #{cloud['name']}".strip
105
122
  end
123
+ if user
124
+ subtitles << "User: #{user['username']}".strip
125
+ end
106
126
  if params[:global]
107
127
  subtitles << "(Global)".strip
108
128
  end
@@ -129,15 +149,16 @@ class Morpheus::Cli::PoliciesCommand
129
149
  #for: ref_str,
130
150
  group: policy['site'] ? policy['site']['name'] : '',
131
151
  cloud: policy['zone'] ? policy['zone']['name'] : '',
152
+ user: policy['user'] ? policy['user']['username'] : '',
132
153
  tenants: truncate_string(format_tenants(policy['accounts']), 15),
133
154
  config: truncate_string(config_str, 50),
134
155
  enabled: policy['enabled'] ? 'Yes' : 'No',
135
156
  }
136
157
  row
137
158
  }
138
- columns = [:id, :name, :description, :group, :cloud, :tenants, :type, :config, :enabled]
139
- if group || cloud
140
- columns = [:id, :description, :type, :config]
159
+ columns = [:id, :name, :description, :group, :cloud, :user, :tenants, :type, :config, :enabled]
160
+ if group || cloud || user
161
+ columns = columns - [:group, :cloud, :user]
141
162
  end
142
163
  if options[:include_fields]
143
164
  columns = options[:include_fields]
@@ -159,6 +180,15 @@ class Morpheus::Cli::PoliciesCommand
159
180
  options = {}
160
181
  optparse = Morpheus::Cli::OptionParser.new do |opts|
161
182
  opts.banner = subcommand_usage("[policy]")
183
+ opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
184
+ options[:group] = val
185
+ end
186
+ opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
187
+ options[:cloud] = val
188
+ end
189
+ # opts.on( '-u', '--user USER', "Username or ID" ) do |val|
190
+ # options[:user] = val
191
+ # end
162
192
  build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
163
193
  opts.footer = "Get details about a policy." + "\n" +
164
194
  "[policy] is required. This is the id of a policy."
@@ -171,15 +201,38 @@ class Morpheus::Cli::PoliciesCommand
171
201
  end
172
202
  connect(options)
173
203
  begin
204
+ group, cloud, user = nil, nil, nil
205
+ if options[:group]
206
+ group = find_group_by_name_or_id(options[:group])
207
+ return 1 if group.nil?
208
+ elsif options[:cloud]
209
+ cloud = find_cloud_by_name_or_id(options[:cloud])
210
+ return 1 if cloud.nil?
211
+ elsif options[:user]
212
+ user = find_user_by_username_or_id(nil, options[:user])
213
+ return 1 if user.nil?
214
+ end
174
215
  if options[:dry_run]
175
216
  if args[0].to_s =~ /\A\d{1,}\Z/
176
- print_dry_run @policies_interface.dry.get(args[0].to_i)
217
+ if group
218
+ print_dry_run @group_policies_interface.dry.get(group['id'], args[0].to_i)
219
+ elsif cloud
220
+ print_dry_run @cloud_policies_interface.dry.get(cloud['id'], args[0].to_i)
221
+ else
222
+ print_dry_run @policies_interface.dry.get(args[0].to_i)
223
+ end
177
224
  else
178
- print_dry_run @policies_interface.dry.list({name:args[0]})
225
+ if group
226
+ print_dry_run @group_policies_interface.dry.list(group['id'], {name:args[0]})
227
+ elsif cloud
228
+ print_dry_run @cloud_policies_interface.dry.list(cloud['id'], {name:args[0]})
229
+ else
230
+ print_dry_run @policies_interface.dry.list({name:args[0]})
231
+ end
179
232
  end
180
233
  return
181
234
  end
182
- policy = find_policy_by_name_or_id(args[0])
235
+ policy = find_policy_by_name_or_id(args[0], {cloud:cloud,group:group})
183
236
  return 1 if policy.nil?
184
237
  json_response = {'policy' => policy} # skip redundant request
185
238
  # json_response = @policies_interface.get(policy['id'])
@@ -203,12 +256,12 @@ class Morpheus::Cli::PoliciesCommand
203
256
  "Type" => lambda {|it| it['policyType'] ? it['policyType']['name'] : '' },
204
257
  "Group" => lambda {|it| it['site'] ? it['site']['name'] : '' },
205
258
  "Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
206
- "Enabled" => lambda {|it| it['enabled'] ? 'Yes' : 'No' },
207
259
  # "All Accounts" => lambda {|it| it['allAccounts'] ? 'Yes' : 'No' },
208
260
  # "Ref Type" => 'refType',
209
261
  # "Ref ID" => 'refId',
210
262
  # "Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
211
263
  "Tenants" => lambda {|it| format_tenants(policy["accounts"]) },
264
+ "Enabled" => lambda {|it| it['enabled'] ? 'Yes' : 'No' }
212
265
  }
213
266
  print_description_list(description_cols, policy)
214
267
  # print reset,"\n"
@@ -235,6 +288,9 @@ class Morpheus::Cli::PoliciesCommand
235
288
  opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID, for scoping the policy to a cloud" ) do |val|
236
289
  options[:cloud] = val
237
290
  end
291
+ opts.on( '-u', '--user USER', "Username or ID, for scoping the policy to a user" ) do |val|
292
+ options[:user] = val
293
+ end
238
294
  opts.on('-t', '--type ID', "Policy Type Name or ID") do |val|
239
295
  options['type'] = val
240
296
  end
@@ -263,7 +319,7 @@ class Morpheus::Cli::PoliciesCommand
263
319
  opts.on('--config-file FILE', String, "Policy Config from a local JSON or YAML file") do |val|
264
320
  options['configFile'] = val.to_s
265
321
  end
266
- build_common_options(opts, options, [:options, :json, :dry_run, :quiet, :remote])
322
+ build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
267
323
  opts.footer = "Create a new policy." + "\n" +
268
324
  "[name] is optional and can be passed as --name instead."
269
325
  end
@@ -275,118 +331,134 @@ class Morpheus::Cli::PoliciesCommand
275
331
  end
276
332
  connect(options)
277
333
  begin
278
- group, cloud = nil, nil
279
- if options[:group]
280
- group = find_group_by_name_or_id(options[:group])
281
- elsif options[:cloud]
282
- cloud = find_cloud_by_name_or_id(options[:cloud])
283
- end
284
-
285
- # merge -O options into normally parsed options
286
- options.deep_merge!(options[:options]) if options[:options] && options[:options].keys.size > 0
287
-
288
- # support [name] as first argument
289
- if args[0]
290
- options['name'] = args[0]
291
- end
334
+ payload = nil
335
+ if options[:payload]
336
+ payload = options[:payload]
337
+ # support -O OPTION switch on top of --payload
338
+ payload.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
339
+ else
340
+ group, cloud, user = nil, nil, nil
341
+ if options[:group]
342
+ group = find_group_by_name_or_id(options[:group])
343
+ elsif options[:cloud]
344
+ cloud = find_cloud_by_name_or_id(options[:cloud])
345
+ elsif options[:user]
346
+ user = find_user_by_username_or_id(nil, options[:user])
347
+ return 1 if user.nil?
348
+ end
292
349
 
293
- # construct payload
294
- payload = {
295
- 'policy' => {
296
- 'config' => {}
297
- }
298
- }
299
-
300
- # prompt for policy options
350
+ # merge -O options into normally parsed options
351
+ options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options] && options[:options].keys.size > 0
352
+
353
+ # support [name] as first argument
354
+ if args[0]
355
+ options['name'] = args[0]
356
+ end
301
357
 
302
- # Policy Type
303
- # allow user as id, name or code
304
- available_policy_types = @policies_interface.list_policy_types({})['policyTypes']
305
- if available_policy_types.empty?
306
- print_red_alert "No available policy types found!"
307
- return 1
308
- end
309
- policy_types_dropdown = available_policy_types.collect {|it| {'name' => it['name'], 'value' => it['id']} }
310
- policy_type_id = nil
311
- policy_type = nil
312
- if options['type']
313
- policy_type_id = options['type']
314
- else
315
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Policy Type', 'type' => 'select', 'selectOptions' => policy_types_dropdown, 'required' => true, 'description' => 'Choose a policy type.'}], options[:options])
316
- policy_type_id = v_prompt['type']
317
- end
318
- if !policy_type_id.to_s.empty?
319
- policy_type = available_policy_types.find {|it|
320
- it['id'] == policy_type_id.to_i || it['name'] == policy_type_id.to_s || it['code'] == policy_type_id.to_s
358
+ # construct payload
359
+ payload = {
360
+ 'policy' => {
361
+ 'config' => {}
362
+ }
321
363
  }
322
- end
323
- if !policy_type
324
- print_red_alert "Policy Type not found by id '#{policy_type_id}'"
325
- return 1
326
- end
327
- # payload['policy']['policyTypeId'] = policy_type['id']
328
- payload['policy']['policyType'] = {'id' => policy_type['id']}
329
-
330
- # Name (this is not even used at the moment!)
331
- if options['name']
332
- payload['policy']['name'] = options['name']
333
- else
334
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false, 'description' => 'Name for this policy.'}], options)
335
- payload['policy']['name'] = v_prompt['name']
336
- end
364
+
365
+ # prompt for policy options
366
+
367
+ # Policy Type
368
+ # allow user as id, name or code
369
+ available_policy_types = @policies_interface.list_policy_types({})['policyTypes']
370
+ if available_policy_types.empty?
371
+ print_red_alert "No available policy types found!"
372
+ return 1
373
+ end
374
+ policy_types_dropdown = available_policy_types.collect {|it| {'name' => it['name'], 'value' => it['id']} }
375
+ policy_type_id = nil
376
+ policy_type = nil
377
+ if options['type']
378
+ policy_type_id = options['type']
379
+ else
380
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'type', 'fieldLabel' => 'Policy Type', 'type' => 'select', 'selectOptions' => policy_types_dropdown, 'required' => true, 'description' => 'Choose a policy type.'}], options[:options])
381
+ policy_type_id = v_prompt['type']
382
+ end
383
+ if !policy_type_id.to_s.empty?
384
+ policy_type = available_policy_types.find {|it|
385
+ it['id'] == policy_type_id.to_i || it['name'] == policy_type_id.to_s || it['code'] == policy_type_id.to_s
386
+ }
387
+ end
388
+ if !policy_type
389
+ print_red_alert "Policy Type not found by id '#{policy_type_id}'"
390
+ return 1
391
+ end
392
+ # payload['policy']['policyTypeId'] = policy_type['id']
393
+ payload['policy']['policyType'] = {'id' => policy_type['id']}
337
394
 
338
- # Description (this is not even used at the moment!)
339
- if options['description']
340
- payload['policy']['description'] = options['description']
341
- else
342
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false, 'description' => 'Description of policy.'}], options)
343
- payload['policy']['description'] = v_prompt['description']
344
- end
395
+ # Scope
396
+ if user
397
+ payload['policy']['refType'] = 'User'
398
+ payload['policy']['refId'] = user['id']
399
+ end
345
400
 
346
- # Enabled
347
- if options['enabled']
348
- payload['policy']['enabled'] = options['enabled']
349
- else
350
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'description' => 'Can be used to disable a policy', 'defaultValue' => true}], options)
351
- payload['policy']['enabled'] = v_prompt['enabled']
352
- end
401
+ # Name (this is not even used at the moment!)
402
+ if options['name']
403
+ payload['policy']['name'] = options['name']
404
+ else
405
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false, 'description' => 'Name for this policy.'}], options)
406
+ payload['policy']['name'] = v_prompt['name']
407
+ end
353
408
 
354
- # Tenants
355
- if options['accounts']
356
- # payload['policy']['accounts'] = options['accounts'].collect {|it| {'id' => it } }
357
- payload['policy']['accounts'] = options['accounts']
358
- else
359
- v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'accounts', 'fieldLabel' => 'Tenants', 'type' => 'text', 'required' => false, 'description' => 'Tenant accounts, comma separated list of account IDs'}], options)
360
- payload['policy']['accounts'] = v_prompt['accounts']
361
- end
409
+ # Description (this is not even used at the moment!)
410
+ if options['description']
411
+ payload['policy']['description'] = options['description']
412
+ else
413
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false, 'description' => 'Description of policy.'}], options)
414
+ payload['policy']['description'] = v_prompt['description']
415
+ end
362
416
 
363
- # Config
364
- if options['config']
365
- payload['policy']['config'] = options['config']
366
- elsif options['configFile']
367
- config_file = File.expand_path(options['configFile'])
368
- if !File.exists?(config_file) || !File.file?(config_file)
369
- print_red_alert "File not found: #{config_file}"
370
- return false
417
+ # Enabled
418
+ if options['enabled']
419
+ payload['policy']['enabled'] = options['enabled']
420
+ else
421
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'enabled', 'fieldLabel' => 'Enabled', 'type' => 'checkbox', 'required' => false, 'description' => 'Can be used to disable a policy', 'defaultValue' => true}], options)
422
+ payload['policy']['enabled'] = v_prompt['enabled']
371
423
  end
372
- if config_file =~ /\.ya?ml\Z/
373
- payload['policy']['config'] = YAML.load_file(config_file)
424
+
425
+ # Tenants
426
+ if options['accounts']
427
+ # payload['policy']['accounts'] = options['accounts'].collect {|it| {'id' => it } }
428
+ payload['policy']['accounts'] = options['accounts']
374
429
  else
375
- payload['policy']['config'] = JSON.parse(File.read(config_file))
430
+ v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'accounts', 'fieldLabel' => 'Tenants', 'type' => 'text', 'required' => false, 'description' => 'Tenant accounts, comma separated list of account IDs'}], options)
431
+ payload['policy']['accounts'] = v_prompt['accounts']
376
432
  end
377
- else
378
- # prompt for policy specific options
379
- policy_type_option_types = policy_type['optionTypes']
380
- # puts "POLICY OPTION TYPES:\n #{policy_type_option_types.inspect}"
381
- if policy_type_option_types
382
- config_prompt = Morpheus::Cli::OptionTypes.prompt(policy_type_option_types, options, @api_client)
383
- # everything should be under fieldContext:'config'
384
- # payload['policy'].deep_merge!(config_prompt)
385
- if config_prompt['config']
386
- payload['policy']['config'].deep_merge!(config_prompt['config'])
433
+
434
+ # Config
435
+ if options['config']
436
+ payload['policy']['config'] = options['config']
437
+ elsif options['configFile']
438
+ config_file = File.expand_path(options['configFile'])
439
+ if !File.exists?(config_file) || !File.file?(config_file)
440
+ print_red_alert "File not found: #{config_file}"
441
+ return false
442
+ end
443
+ if config_file =~ /\.ya?ml\Z/
444
+ payload['policy']['config'] = YAML.load_file(config_file)
445
+ else
446
+ payload['policy']['config'] = JSON.parse(File.read(config_file))
387
447
  end
388
448
  else
389
- puts "No options found for policy type! Proceeding without config options..."
449
+ # prompt for policy specific options
450
+ policy_type_option_types = policy_type['optionTypes']
451
+ # puts "POLICY OPTION TYPES:\n #{policy_type_option_types.inspect}"
452
+ if policy_type_option_types
453
+ config_prompt = Morpheus::Cli::OptionTypes.prompt(policy_type_option_types, options, @api_client)
454
+ # everything should be under fieldContext:'config'
455
+ # payload['policy'].deep_merge!(config_prompt)
456
+ if config_prompt['config']
457
+ payload['policy']['config'].deep_merge!(config_prompt['config'])
458
+ end
459
+ else
460
+ puts "No options found for policy type! Proceeding without config options..."
461
+ end
390
462
  end
391
463
  end
392
464
 
@@ -762,17 +834,26 @@ class Morpheus::Cli::PoliciesCommand
762
834
 
763
835
  private
764
836
 
765
- def find_policy_by_name_or_id(val)
837
+ def find_policy_by_name_or_id(val, scope_by={})
766
838
  if val.to_s =~ /\A\d{1,}\Z/
767
- return find_policy_by_id(val)
839
+ return find_policy_by_id(val, scope_by)
768
840
  else
769
- return find_policy_by_name(val)
841
+ return find_policy_by_name(val, scope_by)
770
842
  end
771
843
  end
772
844
 
773
- def find_policy_by_id(id)
845
+ def find_policy_by_id(id, scope_by={})
774
846
  begin
775
- json_response = @policies_interface.get(id.to_i)
847
+ group = scope_by[:group]
848
+ cloud = scope_by[:cloud]
849
+ json_response = nil
850
+ if group
851
+ json_response = @group_policies_interface.get(group['id'], id.to_i)
852
+ elsif cloud
853
+ json_response = @cloud_policies_interface.get(cloud['id'], id.to_i)
854
+ else
855
+ json_response = @policies_interface.get(id.to_i)
856
+ end
776
857
  return json_response['policy']
777
858
  rescue RestClient::Exception => e
778
859
  if e.response && e.response.code == 404
@@ -784,8 +865,17 @@ class Morpheus::Cli::PoliciesCommand
784
865
  end
785
866
  end
786
867
 
787
- def find_policy_by_name(name)
788
- json_response = @policies_interface.list({name: name.to_s})
868
+ def find_policy_by_name(name, scope_by={})
869
+ group = scope_by[:group]
870
+ cloud = scope_by[:cloud]
871
+ json_response = nil
872
+ if group
873
+ json_response = @group_policies_interface.list(group['id'], {name: name.to_s})
874
+ elsif cloud
875
+ json_response = @cloud_policies_interface.list(cloud['id'], {name: name.to_s})
876
+ else
877
+ json_response = @policies_interface.list({name: name.to_s})
878
+ end
789
879
  policies = json_response['policies']
790
880
  if policies.empty?
791
881
  print_red_alert "Policy not found by name #{name}"