morpheus-cli 3.1.1 → 3.1.1.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.
- checksums.yaml +4 -4
- data/lib/morpheus/api/api_client.rb +40 -0
- data/lib/morpheus/api/cloud_policies_interface.rb +47 -0
- data/lib/morpheus/api/group_policies_interface.rb +47 -0
- data/lib/morpheus/api/network_domains_interface.rb +47 -0
- data/lib/morpheus/api/network_groups_interface.rb +47 -0
- data/lib/morpheus/api/network_pool_servers_interface.rb +47 -0
- data/lib/morpheus/api/network_pools_interface.rb +47 -0
- data/lib/morpheus/api/network_proxies_interface.rb +47 -0
- data/lib/morpheus/api/network_services_interface.rb +47 -0
- data/lib/morpheus/api/networks_interface.rb +54 -0
- data/lib/morpheus/api/policies_interface.rb +63 -0
- data/lib/morpheus/cli.rb +8 -4
- data/lib/morpheus/cli/cli_command.rb +36 -1
- data/lib/morpheus/cli/instances.rb +3 -25
- data/lib/morpheus/cli/network_domains_command.rb +571 -0
- data/lib/morpheus/cli/network_groups_command.rb +602 -0
- data/lib/morpheus/cli/network_pool_servers_command.rb +430 -0
- data/lib/morpheus/cli/network_pools_command.rb +495 -0
- data/lib/morpheus/cli/network_proxies_command.rb +594 -0
- data/lib/morpheus/cli/network_services_command.rb +148 -0
- data/lib/morpheus/cli/networks_command.rb +855 -0
- data/lib/morpheus/cli/option_types.rb +3 -3
- data/lib/morpheus/cli/policies_command.rb +847 -0
- data/lib/morpheus/cli/remote.rb +0 -1
- data/lib/morpheus/cli/roles.rb +2 -2
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +20 -2
@@ -194,7 +194,7 @@ module Morpheus
|
|
194
194
|
value_found = false
|
195
195
|
value = nil
|
196
196
|
while !value_found do
|
197
|
-
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{option_type['defaultValue'] ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
|
197
|
+
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
|
198
198
|
input = $stdin.gets.chomp!
|
199
199
|
value = input.empty? ? option_type['defaultValue'] : input
|
200
200
|
value = value.to_s.include?('.') ? value.to_f : value.to_i
|
@@ -271,7 +271,7 @@ module Morpheus
|
|
271
271
|
}
|
272
272
|
matches
|
273
273
|
}
|
274
|
-
input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{
|
274
|
+
input = Readline.readline("#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''} ['?' for options]: ", false).to_s
|
275
275
|
input = input.chomp.strip
|
276
276
|
if input.empty?
|
277
277
|
value = option_type['defaultValue']
|
@@ -335,7 +335,7 @@ module Morpheus
|
|
335
335
|
value_found = false
|
336
336
|
value = nil
|
337
337
|
while !value_found do
|
338
|
-
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{
|
338
|
+
print "#{option_type['fieldLabel']}#{option_type['fieldAddOn'] ? ('(' + option_type['fieldAddOn'] + ') ') : '' }#{!option_type['required'] ? ' (optional)' : ''}#{!option_type['defaultValue'].to_s.empty? ? ' ['+option_type['defaultValue'].to_s+']' : ''}: "
|
339
339
|
input = $stdin.gets.chomp!
|
340
340
|
value = input.empty? ? option_type['defaultValue'] : input
|
341
341
|
if input == '?'
|
@@ -0,0 +1,847 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'rest_client'
|
4
|
+
require 'optparse'
|
5
|
+
require 'filesize'
|
6
|
+
require 'table_print'
|
7
|
+
require 'morpheus/cli/cli_command'
|
8
|
+
require 'morpheus/cli/mixins/infrastructure_helper'
|
9
|
+
|
10
|
+
class Morpheus::Cli::PoliciesCommand
|
11
|
+
include Morpheus::Cli::CliCommand
|
12
|
+
include Morpheus::Cli::InfrastructureHelper
|
13
|
+
|
14
|
+
set_command_name :policies
|
15
|
+
|
16
|
+
register_subcommands :list, :get, :add, :update, :remove #, :generate_pool
|
17
|
+
register_subcommands :'list-types' => :list_types
|
18
|
+
register_subcommands :'get-type' => :get_type
|
19
|
+
|
20
|
+
# set_default_subcommand :list
|
21
|
+
|
22
|
+
def initialize()
|
23
|
+
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
24
|
+
end
|
25
|
+
|
26
|
+
def connect(opts)
|
27
|
+
@api_client = establish_remote_appliance_connection(opts)
|
28
|
+
# @policies_interface = Morpheus::APIClient.new(@access_token,nil,nil, @appliance_url).policies
|
29
|
+
@policies_interface = @api_client.policies
|
30
|
+
@group_policies_interface = @api_client.group_policies
|
31
|
+
@cloud_policies_interface = @api_client.cloud_policies
|
32
|
+
@clouds_interface = @api_client.clouds
|
33
|
+
@groups_interface = @api_client.groups
|
34
|
+
@active_group_id = Morpheus::Cli::Groups.active_groups[@appliance_name]
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle(args)
|
38
|
+
handle_subcommand(args)
|
39
|
+
end
|
40
|
+
|
41
|
+
def list(args)
|
42
|
+
options = {}
|
43
|
+
params = {}
|
44
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
45
|
+
opts.banner = subcommand_usage()
|
46
|
+
opts.on( '-g', '--group GROUP', "Group Name or ID" ) do |val|
|
47
|
+
options[:group] = val
|
48
|
+
end
|
49
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID" ) do |val|
|
50
|
+
options[:cloud] = val
|
51
|
+
end
|
52
|
+
opts.on( '-G', '--global', "Exclude policies scoped to a group or cloud" ) do
|
53
|
+
params[:global] = true
|
54
|
+
end
|
55
|
+
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
|
56
|
+
opts.footer = "List policies."
|
57
|
+
end
|
58
|
+
optparse.parse!(args)
|
59
|
+
connect(options)
|
60
|
+
begin
|
61
|
+
group, cloud = nil, nil
|
62
|
+
if options[:group]
|
63
|
+
group = find_group_by_name_or_id(options[:group])
|
64
|
+
elsif options[:cloud]
|
65
|
+
cloud = find_cloud_by_name_or_id(options[:cloud])
|
66
|
+
end
|
67
|
+
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
68
|
+
params[k] = options[k] unless options[k].nil?
|
69
|
+
end
|
70
|
+
if options[:dry_run]
|
71
|
+
if group
|
72
|
+
print_dry_run @group_policies_interface.dry.list(group['id'], params)
|
73
|
+
elsif cloud
|
74
|
+
print_dry_run @cloud_policies_interface.dry.list(cloud['id'], params)
|
75
|
+
else
|
76
|
+
# global
|
77
|
+
print_dry_run @policies_interface.dry.list(params)
|
78
|
+
end
|
79
|
+
return 0
|
80
|
+
end
|
81
|
+
json_response = nil
|
82
|
+
if group
|
83
|
+
json_response = @group_policies_interface.list(group['id'], params)
|
84
|
+
elsif cloud
|
85
|
+
json_response = @cloud_policies_interface.list(cloud['id'], params)
|
86
|
+
else
|
87
|
+
json_response = @policies_interface.list(params)
|
88
|
+
end
|
89
|
+
policies = json_response["policies"]
|
90
|
+
if options[:include_fields]
|
91
|
+
json_response = {"policies" => filter_data(policies, options[:include_fields]) }
|
92
|
+
end
|
93
|
+
if options[:json]
|
94
|
+
puts as_json(json_response, options)
|
95
|
+
return 0
|
96
|
+
elsif options[:yaml]
|
97
|
+
puts as_yaml(json_response, options)
|
98
|
+
return 0
|
99
|
+
elsif options[:csv]
|
100
|
+
puts records_as_csv(policies, options)
|
101
|
+
return 0
|
102
|
+
end
|
103
|
+
title = "Morpheus Policies"
|
104
|
+
subtitles = []
|
105
|
+
if group
|
106
|
+
subtitles << "Group: #{group['name']}".strip
|
107
|
+
end
|
108
|
+
if cloud
|
109
|
+
subtitles << "Cloud: #{cloud['name']}".strip
|
110
|
+
end
|
111
|
+
if params[:global]
|
112
|
+
subtitles << "(Global)".strip
|
113
|
+
end
|
114
|
+
if params[:phrase]
|
115
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
116
|
+
end
|
117
|
+
print_h1 title, subtitles
|
118
|
+
if policies.empty?
|
119
|
+
print cyan,"No policies found.",reset,"\n"
|
120
|
+
else
|
121
|
+
rows = policies.collect {|policy|
|
122
|
+
# we got a policy.site and policy.zone now!
|
123
|
+
# ref_type, ref_id = policy['refType'], policy['refId']
|
124
|
+
# ref_str = ""
|
125
|
+
# if ref_type == 'ComputeZone'
|
126
|
+
# ref_str = "Cloud #{ref_id}"
|
127
|
+
# elsif ref_type == 'ComputeSite'
|
128
|
+
# ref_str = "Group #{ref_id}"
|
129
|
+
# end
|
130
|
+
config_str = JSON.generate(policy['config'] || {})
|
131
|
+
row = {
|
132
|
+
id: policy['id'],
|
133
|
+
name: policy['name'], # always blank right now?
|
134
|
+
description: policy['description'], # always blank right now?
|
135
|
+
type: policy['policyType'] ? policy['policyType']['name'] : '',
|
136
|
+
#for: ref_str,
|
137
|
+
group: policy['site'] ? policy['site']['name'] : '',
|
138
|
+
cloud: policy['zone'] ? policy['zone']['name'] : '',
|
139
|
+
tenants: truncate_string(format_tenants(policy['accounts']), 15),
|
140
|
+
config: truncate_string(config_str, 50),
|
141
|
+
enabled: policy['enabled'] ? 'Yes' : 'No',
|
142
|
+
}
|
143
|
+
row
|
144
|
+
}
|
145
|
+
columns = [:id, :name, :description, :group, :cloud, :tenants, :type, :config, :enabled]
|
146
|
+
if group || cloud
|
147
|
+
columns = [:id, :description, :type, :config]
|
148
|
+
end
|
149
|
+
if options[:include_fields]
|
150
|
+
columns = options[:include_fields]
|
151
|
+
end
|
152
|
+
print cyan
|
153
|
+
print as_pretty_table(rows, columns, options)
|
154
|
+
print reset
|
155
|
+
print_results_pagination(json_response, {:label => "policy", :n_label => "policies"})
|
156
|
+
end
|
157
|
+
print reset,"\n"
|
158
|
+
return 0
|
159
|
+
rescue RestClient::Exception => e
|
160
|
+
print_rest_exception(e, options)
|
161
|
+
exit 1
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def get(args)
|
166
|
+
options = {}
|
167
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
168
|
+
opts.banner = subcommand_usage("[policy]")
|
169
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
170
|
+
opts.footer = "Get details about a policy." + "\n" +
|
171
|
+
"[policy] is required. This is the id of a policy."
|
172
|
+
end
|
173
|
+
optparse.parse!(args)
|
174
|
+
if args.count != 1
|
175
|
+
print_error Morpheus::Terminal.angry_prompt
|
176
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
177
|
+
return 1
|
178
|
+
end
|
179
|
+
connect(options)
|
180
|
+
begin
|
181
|
+
if options[:dry_run]
|
182
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
183
|
+
print_dry_run @policies_interface.dry.get(args[0].to_i)
|
184
|
+
else
|
185
|
+
print_dry_run @policies_interface.dry.list({name:args[0]})
|
186
|
+
end
|
187
|
+
return
|
188
|
+
end
|
189
|
+
policy = find_policy_by_name_or_id(args[0])
|
190
|
+
return 1 if policy.nil?
|
191
|
+
json_response = {'policy' => policy} # skip redundant request
|
192
|
+
# json_response = @policies_interface.get(policy['id'])
|
193
|
+
policy = json_response['policy']
|
194
|
+
if options[:include_fields]
|
195
|
+
json_response = {'policy' => filter_data(policy, options[:include_fields]) }
|
196
|
+
end
|
197
|
+
if options[:json]
|
198
|
+
puts as_json(json_response, options)
|
199
|
+
return 0
|
200
|
+
elsif options[:yaml]
|
201
|
+
puts as_yaml(json_response, options)
|
202
|
+
return 0
|
203
|
+
elsif options[:csv]
|
204
|
+
puts records_as_csv([policy], options)
|
205
|
+
return 0
|
206
|
+
end
|
207
|
+
print_h1 "Policy Details"
|
208
|
+
print cyan
|
209
|
+
description_cols = {
|
210
|
+
"ID" => 'id',
|
211
|
+
"Name" => 'name',
|
212
|
+
"Description" => 'description',
|
213
|
+
"Type" => lambda {|it| it['policyType'] ? it['policyType']['name'] : '' },
|
214
|
+
"Group" => lambda {|it| it['site'] ? it['site']['name'] : '' },
|
215
|
+
"Cloud" => lambda {|it| it['zone'] ? it['zone']['name'] : '' },
|
216
|
+
"Enabled" => lambda {|it| it['enabled'] ? 'Yes' : 'No' },
|
217
|
+
# "All Accounts" => lambda {|it| it['allAccounts'] ? 'Yes' : 'No' },
|
218
|
+
# "Ref Type" => 'refType',
|
219
|
+
# "Ref ID" => 'refId',
|
220
|
+
# "Owner" => lambda {|it| it['owner'] ? it['owner']['name'] : '' },
|
221
|
+
"Tenants" => lambda {|it| format_tenants(policy["accounts"]) },
|
222
|
+
}
|
223
|
+
print_description_list(description_cols, policy)
|
224
|
+
# print reset,"\n"
|
225
|
+
|
226
|
+
print_h2 "Policy Config"
|
227
|
+
print cyan
|
228
|
+
puts as_json(policy['config'])
|
229
|
+
print reset, "\n"
|
230
|
+
return 0
|
231
|
+
rescue RestClient::Exception => e
|
232
|
+
print_rest_exception(e, options)
|
233
|
+
return 1
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def add(args)
|
238
|
+
options = {}
|
239
|
+
policy_type_id = nil
|
240
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
241
|
+
opts.banner = subcommand_usage("-t TYPE")
|
242
|
+
opts.on( '-g', '--group GROUP', "Group Name or ID, for scoping the policy to a group." ) do |val|
|
243
|
+
options[:group] = val
|
244
|
+
end
|
245
|
+
opts.on( '-c', '--cloud CLOUD', "Cloud Name or ID, for scoping the policy to a cloud" ) do |val|
|
246
|
+
options[:cloud] = val
|
247
|
+
end
|
248
|
+
opts.on('-t', '--type ID', "Policy Type Name or ID") do |val|
|
249
|
+
options['type'] = val
|
250
|
+
end
|
251
|
+
opts.on('--name VALUE', String, "Name for this policy") do |val|
|
252
|
+
options['name'] = val
|
253
|
+
end
|
254
|
+
opts.on('--description VALUE', String, "Description of policy") do |val|
|
255
|
+
options['description'] = val
|
256
|
+
end
|
257
|
+
opts.on('--accounts LIST', Array, "Tenant accounts, comma separated list of account IDs") do |list|
|
258
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
259
|
+
options['accounts'] = []
|
260
|
+
else
|
261
|
+
options['accounts'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
262
|
+
end
|
263
|
+
end
|
264
|
+
opts.on('--enabled [on|off]', String, "Can be used to disable a policy") do |val|
|
265
|
+
options['enabled'] = val.to_s == 'on' || val.to_s == 'true'
|
266
|
+
end
|
267
|
+
opts.on('--config JSON', String, "Policy Config JSON") do |val|
|
268
|
+
options['config'] = JSON.parse(val.to_s)
|
269
|
+
end
|
270
|
+
opts.on('--config-yaml YAML', String, "Policy Config YAML") do |val|
|
271
|
+
options['config'] = YAML.load(val.to_s)
|
272
|
+
end
|
273
|
+
opts.on('--config-file FILE', String, "Policy Config from a local JSON or YAML file") do |val|
|
274
|
+
options['configFile'] = val.to_s
|
275
|
+
end
|
276
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :quiet, :remote])
|
277
|
+
opts.footer = "Create a new policy." + "\n" +
|
278
|
+
"[name] is optional and can be passed as --name instead."
|
279
|
+
end
|
280
|
+
optparse.parse!(args)
|
281
|
+
if args.count > 1
|
282
|
+
print_error Morpheus::Terminal.angry_prompt
|
283
|
+
puts_error "wrong number of arguments, expected 0-1 and got #{args.count}\n#{optparse}"
|
284
|
+
return 1
|
285
|
+
end
|
286
|
+
connect(options)
|
287
|
+
begin
|
288
|
+
group, cloud = nil, nil
|
289
|
+
if options[:group]
|
290
|
+
group = find_group_by_name_or_id(options[:group])
|
291
|
+
elsif options[:cloud]
|
292
|
+
cloud = find_cloud_by_name_or_id(options[:cloud])
|
293
|
+
end
|
294
|
+
|
295
|
+
# merge -O options into normally parsed options
|
296
|
+
options.deep_merge!(options[:options]) if options[:options] && options[:options].keys.size > 0
|
297
|
+
|
298
|
+
# support [name] as first argument
|
299
|
+
if args[0]
|
300
|
+
options['name'] = args[0]
|
301
|
+
end
|
302
|
+
|
303
|
+
# construct payload
|
304
|
+
payload = {
|
305
|
+
'policy' => {
|
306
|
+
'config' => {}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
# prompt for policy options
|
311
|
+
|
312
|
+
# Policy Type
|
313
|
+
# allow user as id, name or code
|
314
|
+
available_policy_types = @policies_interface.list_policy_types({})['policyTypes']
|
315
|
+
if available_policy_types.empty?
|
316
|
+
print_red_alert "No available policy types found!"
|
317
|
+
return 1
|
318
|
+
end
|
319
|
+
policy_types_dropdown = available_policy_types.collect {|it| {'name' => it['name'], 'value' => it['id']} }
|
320
|
+
policy_type_id = nil
|
321
|
+
policy_type = nil
|
322
|
+
if options['type']
|
323
|
+
policy_type_id = options['type']
|
324
|
+
else
|
325
|
+
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])
|
326
|
+
policy_type_id = v_prompt['type']
|
327
|
+
end
|
328
|
+
if !policy_type_id.to_s.empty?
|
329
|
+
policy_type = available_policy_types.find {|it|
|
330
|
+
it['id'] == policy_type_id.to_i || it['name'] == policy_type_id.to_s || it['code'] == policy_type_id.to_s
|
331
|
+
}
|
332
|
+
end
|
333
|
+
if !policy_type
|
334
|
+
print_red_alert "Policy Type not found by id '#{policy_type_id}'"
|
335
|
+
return 1
|
336
|
+
end
|
337
|
+
# payload['policy']['policyTypeId'] = policy_type['id']
|
338
|
+
payload['policy']['policyType'] = {'id' => policy_type['id']}
|
339
|
+
|
340
|
+
# Name (this is not even used at the moment!)
|
341
|
+
if options['name']
|
342
|
+
payload['policy']['name'] = options['name']
|
343
|
+
else
|
344
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => false, 'description' => 'Name for this policy.'}], options)
|
345
|
+
payload['policy']['name'] = v_prompt['name']
|
346
|
+
end
|
347
|
+
|
348
|
+
# Description (this is not even used at the moment!)
|
349
|
+
if options['description']
|
350
|
+
payload['policy']['description'] = options['description']
|
351
|
+
else
|
352
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'required' => false, 'description' => 'Description of policy.'}], options)
|
353
|
+
payload['policy']['description'] = v_prompt['description']
|
354
|
+
end
|
355
|
+
|
356
|
+
# Enabled
|
357
|
+
if options['enabled']
|
358
|
+
payload['policy']['enabled'] = options['enabled']
|
359
|
+
else
|
360
|
+
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)
|
361
|
+
payload['policy']['enabled'] = v_prompt['enabled']
|
362
|
+
end
|
363
|
+
|
364
|
+
# Tenants
|
365
|
+
if options['accounts']
|
366
|
+
# payload['policy']['accounts'] = options['accounts'].collect {|it| {'id' => it } }
|
367
|
+
payload['policy']['accounts'] = options['accounts']
|
368
|
+
else
|
369
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'accounts', 'fieldLabel' => 'Tenants', 'type' => 'text', 'required' => false, 'description' => 'Tenant accounts, comma separated list of account IDs'}], options)
|
370
|
+
payload['policy']['accounts'] = v_prompt['accounts']
|
371
|
+
end
|
372
|
+
|
373
|
+
# Config
|
374
|
+
if options['config']
|
375
|
+
payload['policy']['config'] = options['config']
|
376
|
+
elsif options['configFile']
|
377
|
+
config_file = File.expand_path(options['configFile'])
|
378
|
+
if !File.exists?(config_file) || !File.file?(config_file)
|
379
|
+
print_red_alert "File not found: #{config_file}"
|
380
|
+
return false
|
381
|
+
end
|
382
|
+
if config_file =~ /\.ya?ml\Z/
|
383
|
+
payload['policy']['config'] = YAML.load_file(config_file)
|
384
|
+
else
|
385
|
+
payload['policy']['config'] = JSON.parse(File.read(config_file))
|
386
|
+
end
|
387
|
+
else
|
388
|
+
# prompt for policy specific options
|
389
|
+
policy_type_option_types = policy_type['optionTypes']
|
390
|
+
# puts "POLICY OPTION TYPES:\n #{policy_type_option_types.inspect}"
|
391
|
+
if policy_type_option_types
|
392
|
+
config_prompt = Morpheus::Cli::OptionTypes.prompt(policy_type_option_types, options, @api_client)
|
393
|
+
# everything should be under fieldContext:'config'
|
394
|
+
# payload['policy'].deep_merge!(config_prompt)
|
395
|
+
if config_prompt['config']
|
396
|
+
payload['policy']['config'].deep_merge!(config_prompt['config'])
|
397
|
+
end
|
398
|
+
else
|
399
|
+
puts "No options found for policy type! Proceeding without config options..."
|
400
|
+
end
|
401
|
+
end
|
402
|
+
|
403
|
+
|
404
|
+
if options[:dry_run]
|
405
|
+
if group
|
406
|
+
print_dry_run @group_policies_interface.dry.create(group['id'], payload)
|
407
|
+
elsif cloud
|
408
|
+
print_dry_run @cloud_policies_interface.dry.create(cloud['id'], payload)
|
409
|
+
else
|
410
|
+
# global
|
411
|
+
print_dry_run @policies_interface.dry.create(payload)
|
412
|
+
end
|
413
|
+
return
|
414
|
+
end
|
415
|
+
json_response = nil
|
416
|
+
if group
|
417
|
+
json_response = @group_policies_interface.create(group['id'], payload)
|
418
|
+
elsif cloud
|
419
|
+
json_response = @cloud_policies_interface.create(cloud['id'], payload)
|
420
|
+
else
|
421
|
+
# global
|
422
|
+
json_response = @policies_interface.create(payload)
|
423
|
+
end
|
424
|
+
if options[:json]
|
425
|
+
print JSON.pretty_generate(json_response)
|
426
|
+
print "\n"
|
427
|
+
elsif !options[:quiet]
|
428
|
+
print_green_success "Added policy"
|
429
|
+
# list([])
|
430
|
+
policy = json_response['policy']
|
431
|
+
get([policy['id']])
|
432
|
+
end
|
433
|
+
return 0
|
434
|
+
rescue RestClient::Exception => e
|
435
|
+
print_rest_exception(e, options)
|
436
|
+
exit 1
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
def update(args)
|
441
|
+
options = {}
|
442
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
443
|
+
opts.banner = subcommand_usage("[policy] [options]")
|
444
|
+
# opts.on('-t', '--type ID', "Policy Type Name or ID") do |val|
|
445
|
+
# options['type'] = val
|
446
|
+
# end
|
447
|
+
opts.on('--name VALUE', String, "Name for this policy") do |val|
|
448
|
+
options['name'] = val
|
449
|
+
end
|
450
|
+
opts.on('--description VALUE', String, "Description of policy") do |val|
|
451
|
+
options['description'] = val
|
452
|
+
end
|
453
|
+
opts.on('--accounts LIST', Array, "Tenant accounts, comma separated list of account IDs") do |list|
|
454
|
+
if list.size == 1 && list[0] == 'null' # hacky way to clear it
|
455
|
+
options['accounts'] = []
|
456
|
+
else
|
457
|
+
options['accounts'] = list.collect {|it| it.to_s.strip.empty? ? nil : it.to_s.strip }.compact.uniq
|
458
|
+
end
|
459
|
+
end
|
460
|
+
opts.on('--enabled [on|off]', String, "Can be used to disable a policy") do |val|
|
461
|
+
options['enabled'] = val.to_s == 'on' || val.to_s == 'true'
|
462
|
+
end
|
463
|
+
opts.on('--config JSON', String, "Policy Config JSON") do |val|
|
464
|
+
options['config'] = JSON.parse(val.to_s)
|
465
|
+
end
|
466
|
+
opts.on('--config-yaml YAML', String, "Policy Config YAML") do |val|
|
467
|
+
options['config'] = YAML.load(val.to_s)
|
468
|
+
end
|
469
|
+
opts.on('--config-file FILE', String, "Policy Config from a local JSON or YAML file") do |val|
|
470
|
+
options['configFile'] = val.to_s
|
471
|
+
end
|
472
|
+
build_common_options(opts, options, [:options, :json, :dry_run, :remote])
|
473
|
+
opts.footer = "Update a policy." + "\n" +
|
474
|
+
"[policy] is required. This is the id of a policy."
|
475
|
+
end
|
476
|
+
optparse.parse!(args)
|
477
|
+
if args.count != 1
|
478
|
+
print_error Morpheus::Terminal.angry_prompt
|
479
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
480
|
+
return 1
|
481
|
+
end
|
482
|
+
connect(options)
|
483
|
+
|
484
|
+
begin
|
485
|
+
policy = find_policy_by_name_or_id(args[0])
|
486
|
+
return 1 if policy.nil?
|
487
|
+
group = policy['site'] || policy['group']
|
488
|
+
cloud = policy['zone'] || policy['cloud']
|
489
|
+
|
490
|
+
payload = {
|
491
|
+
'policy' => {}
|
492
|
+
}
|
493
|
+
|
494
|
+
# no prompting, just collect all user passed options
|
495
|
+
params = {}
|
496
|
+
params.deep_merge!(options.reject {|k,v| k.is_a?(Symbol) })
|
497
|
+
params.deep_merge!(options[:options]) if options[:options]
|
498
|
+
|
499
|
+
if params.empty?
|
500
|
+
print_error Morpheus::Terminal.angry_prompt
|
501
|
+
puts_error "Specify atleast one option to update\n#{optparse}"
|
502
|
+
return 1
|
503
|
+
end
|
504
|
+
payload['policy'].deep_merge!(params)
|
505
|
+
|
506
|
+
# Config
|
507
|
+
if options['config']
|
508
|
+
payload['policy']['config'] = options['config']
|
509
|
+
elsif options['configFile']
|
510
|
+
config_file = File.expand_path(options['configFile'])
|
511
|
+
if !File.exists?(config_file) || !File.file?(config_file)
|
512
|
+
print_red_alert "File not found: #{config_file}"
|
513
|
+
return false
|
514
|
+
end
|
515
|
+
if config_file =~ /\.ya?ml\Z/
|
516
|
+
payload['policy']['config'] = YAML.load_file(config_file)
|
517
|
+
else
|
518
|
+
payload['policy']['config'] = JSON.parse(File.read(config_file))
|
519
|
+
end
|
520
|
+
else
|
521
|
+
# this allows adding/updating a single config setting.
|
522
|
+
# use --config or --configFile to overwrite the entire config
|
523
|
+
if policy['config'] && payload['policy']['config']
|
524
|
+
payload['policy']['config'] = policy['config'].merge(payload['policy']['config'])
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
# if options[:dry_run]
|
529
|
+
# print_dry_run @policies_interface.dry.update(policy["id"], payload)
|
530
|
+
# return
|
531
|
+
# end
|
532
|
+
# json_response = @policies_interface.update(policy["id"], payload)
|
533
|
+
|
534
|
+
if options[:dry_run]
|
535
|
+
if group
|
536
|
+
print_dry_run @group_policies_interface.dry.update(group['id'], policy["id"], payload)
|
537
|
+
elsif cloud
|
538
|
+
print_dry_run @cloud_policies_interface.dry.update(cloud['id'], policy["id"], payload)
|
539
|
+
else
|
540
|
+
print_dry_run @policies_interface.dry.update(policy["id"], payload)
|
541
|
+
end
|
542
|
+
return
|
543
|
+
end
|
544
|
+
json_response = nil
|
545
|
+
if group
|
546
|
+
json_response = @group_policies_interface.update(group['id'], policy["id"], payload)
|
547
|
+
elsif cloud
|
548
|
+
json_response = @cloud_policies_interface.update(cloud['id'], policy["id"], payload)
|
549
|
+
else
|
550
|
+
json_response = @policies_interface.update(policy["id"], payload)
|
551
|
+
end
|
552
|
+
if options[:json]
|
553
|
+
puts as_json(json_response)
|
554
|
+
else
|
555
|
+
print_green_success "Updated policy #{policy['id']}"
|
556
|
+
get([policy['id']])
|
557
|
+
end
|
558
|
+
return 0
|
559
|
+
rescue RestClient::Exception => e
|
560
|
+
print_rest_exception(e, options)
|
561
|
+
return 1
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
def remove(args)
|
566
|
+
options = {}
|
567
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
568
|
+
opts.banner = subcommand_usage("[policy]")
|
569
|
+
build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
|
570
|
+
opts.footer = "Delete a policy." + "\n" +
|
571
|
+
"[policy] is required. This is the id of a policy."
|
572
|
+
end
|
573
|
+
optparse.parse!(args)
|
574
|
+
|
575
|
+
if args.count != 1
|
576
|
+
print_error Morpheus::Terminal.angry_prompt
|
577
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
578
|
+
return 1
|
579
|
+
end
|
580
|
+
|
581
|
+
connect(options)
|
582
|
+
begin
|
583
|
+
policy = find_policy_by_name_or_id(args[0])
|
584
|
+
return 1 if policy.nil?
|
585
|
+
group = policy['site'] || policy['group']
|
586
|
+
cloud = policy['zone'] || policy['cloud']
|
587
|
+
|
588
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the policy: #{policy['id']}?")
|
589
|
+
return 9, "aborted command"
|
590
|
+
end
|
591
|
+
# if options[:dry_run]
|
592
|
+
# print_dry_run @policies_interface.dry.destroy(policy['id'])
|
593
|
+
# return 0
|
594
|
+
# end
|
595
|
+
# json_response = @policies_interface.destroy(policy['id'])
|
596
|
+
if options[:dry_run]
|
597
|
+
if group
|
598
|
+
print_dry_run @group_policies_interface.dry.destroy(group['id'], policy["id"])
|
599
|
+
elsif cloud
|
600
|
+
print_dry_run @cloud_policies_interface.dry.destroy(cloud['id'], policy["id"])
|
601
|
+
else
|
602
|
+
print_dry_run @policies_interface.dry.destroy(policy["id"])
|
603
|
+
end
|
604
|
+
return
|
605
|
+
end
|
606
|
+
json_response = nil
|
607
|
+
if group
|
608
|
+
json_response = @group_policies_interface.destroy(group['id'], policy["id"])
|
609
|
+
elsif cloud
|
610
|
+
json_response = @cloud_policies_interface.destroy(cloud['id'], policy["id"])
|
611
|
+
else
|
612
|
+
json_response = @policies_interface.destroy(policy["id"])
|
613
|
+
end
|
614
|
+
if options[:json]
|
615
|
+
print JSON.pretty_generate(json_response)
|
616
|
+
print "\n"
|
617
|
+
else
|
618
|
+
print_green_success "Deleted policy #{policy['id']}"
|
619
|
+
# list([])
|
620
|
+
end
|
621
|
+
return 0
|
622
|
+
rescue RestClient::Exception => e
|
623
|
+
print_rest_exception(e, options)
|
624
|
+
return 1
|
625
|
+
end
|
626
|
+
end
|
627
|
+
|
628
|
+
def list_types(args)
|
629
|
+
params = {}
|
630
|
+
options = {}
|
631
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
632
|
+
opts.banner = subcommand_usage()
|
633
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
634
|
+
opts.footer = "List policy types."
|
635
|
+
end
|
636
|
+
optparse.parse!(args)
|
637
|
+
|
638
|
+
if args.count != 0
|
639
|
+
print_error Morpheus::Terminal.angry_prompt
|
640
|
+
puts_error "wrong number of arguments, expected 0 and got #{args.count}\n#{optparse}"
|
641
|
+
return 1
|
642
|
+
end
|
643
|
+
|
644
|
+
connect(options)
|
645
|
+
begin
|
646
|
+
if options[:dry_run]
|
647
|
+
print_dry_run @policies_interface.dry.list_policy_types(params)
|
648
|
+
return 0
|
649
|
+
end
|
650
|
+
json_response = @policies_interface.list_policy_types()
|
651
|
+
policy_types = json_response['policyTypes']
|
652
|
+
if options[:json]
|
653
|
+
puts as_json(json_response)
|
654
|
+
else
|
655
|
+
print_h1 "Morpheus Policy Types"
|
656
|
+
rows = policy_types.collect {|policy_type|
|
657
|
+
row = {
|
658
|
+
id: policy_type['id'],
|
659
|
+
name: policy_type['name'],
|
660
|
+
code: policy_type['code'],
|
661
|
+
description: policy_type['description']
|
662
|
+
}
|
663
|
+
row
|
664
|
+
}
|
665
|
+
columns = [:id, :name]
|
666
|
+
if options[:include_fields]
|
667
|
+
columns = options[:include_fields]
|
668
|
+
end
|
669
|
+
print cyan
|
670
|
+
print as_pretty_table(rows, columns, options)
|
671
|
+
print_results_pagination(json_response, {:label => "policy type", :n_label => "policy types"})
|
672
|
+
print reset, "\n"
|
673
|
+
end
|
674
|
+
return 0
|
675
|
+
rescue RestClient::Exception => e
|
676
|
+
print_rest_exception(e, options)
|
677
|
+
return 1
|
678
|
+
end
|
679
|
+
@policies_interface.list_policy_types
|
680
|
+
end
|
681
|
+
|
682
|
+
def get_type(args)
|
683
|
+
params = {}
|
684
|
+
options = {}
|
685
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
686
|
+
opts.banner = subcommand_usage("[policy-type]")
|
687
|
+
build_common_options(opts, options, [:json, :dry_run, :remote])
|
688
|
+
opts.footer = "Get details about a policy type." + "\n" +
|
689
|
+
"[policy-type] is required. This is ID of a policy type."
|
690
|
+
end
|
691
|
+
optparse.parse!(args)
|
692
|
+
|
693
|
+
if args.count != 1
|
694
|
+
print_error Morpheus::Terminal.angry_prompt
|
695
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
696
|
+
return 1
|
697
|
+
end
|
698
|
+
|
699
|
+
connect(options)
|
700
|
+
begin
|
701
|
+
policy_type_id = args[0].to_s
|
702
|
+
if options[:dry_run]
|
703
|
+
print_dry_run @policies_interface.dry.get_policy_type(policy_type_id, params)
|
704
|
+
return 0
|
705
|
+
end
|
706
|
+
json_response = @policies_interface.get_policy_type(policy_type_id, params)
|
707
|
+
policy_type = json_response['policyType']
|
708
|
+
if options[:json]
|
709
|
+
puts as_json(json_response)
|
710
|
+
else
|
711
|
+
print_h1 "Policy Type Details"
|
712
|
+
print cyan
|
713
|
+
description_cols = {
|
714
|
+
"ID" => 'id',
|
715
|
+
"Name" => 'name',
|
716
|
+
# "Description" => 'description',
|
717
|
+
"Code" => 'code',
|
718
|
+
"Category" => 'category',
|
719
|
+
# "Load Method" => 'loadMethod',
|
720
|
+
# "Enforce Method" => 'enforceMethod',
|
721
|
+
# "Prepare Method" => 'prepareMethod',
|
722
|
+
# "Validate Method" => 'validateMethod',
|
723
|
+
"Provision Enforced" => lambda {|it| it['enforceOnProvision'] ? 'Yes' : 'No' },
|
724
|
+
"Managed Enforced" => lambda {|it| it['enforceOnManaged'] ? 'Yes' : 'No' },
|
725
|
+
}
|
726
|
+
print_description_list(description_cols, policy_type)
|
727
|
+
print reset,"\n"
|
728
|
+
|
729
|
+
# show option types
|
730
|
+
print_h2 "Policy Type Options"
|
731
|
+
policy_type_option_types = policy_type['optionTypes']
|
732
|
+
if !policy_type_option_types || policy_type_option_types.size() == 0
|
733
|
+
puts "No options found for policy type"
|
734
|
+
else
|
735
|
+
rows = policy_type_option_types.collect {|option_type|
|
736
|
+
field_str = option_type['fieldName'].to_s
|
737
|
+
if !option_type['fieldContext'].to_s.empty?
|
738
|
+
field_str = option_type['fieldContext'] + "." + field_str
|
739
|
+
end
|
740
|
+
description_str = option_type['description'].to_s
|
741
|
+
if option_type['helpBlock']
|
742
|
+
if description_str.empty?
|
743
|
+
description_str = option_type['helpBlock']
|
744
|
+
else
|
745
|
+
description_str += " " + option_type['helpBlock']
|
746
|
+
end
|
747
|
+
end
|
748
|
+
row = {
|
749
|
+
#code: option_type['code'],
|
750
|
+
field: field_str,
|
751
|
+
type: option_type['type'],
|
752
|
+
description: description_str,
|
753
|
+
default: option_type['defaultValue'],
|
754
|
+
required: option_type['required'] ? 'Yes' : 'No'
|
755
|
+
}
|
756
|
+
row
|
757
|
+
}
|
758
|
+
columns = [:field, :type, :description, :default, :required]
|
759
|
+
print cyan
|
760
|
+
print as_pretty_table(rows, columns)
|
761
|
+
print reset,"\n"
|
762
|
+
end
|
763
|
+
return 0
|
764
|
+
end
|
765
|
+
return 0
|
766
|
+
rescue RestClient::Exception => e
|
767
|
+
print_rest_exception(e, options)
|
768
|
+
return 1
|
769
|
+
end
|
770
|
+
@policies_interface.list_policy_types
|
771
|
+
end
|
772
|
+
|
773
|
+
private
|
774
|
+
|
775
|
+
def find_policy_by_name_or_id(val)
|
776
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
777
|
+
return find_policy_by_id(val)
|
778
|
+
else
|
779
|
+
return find_policy_by_name(val)
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
def find_policy_by_id(id)
|
784
|
+
begin
|
785
|
+
json_response = @policies_interface.get(id.to_i)
|
786
|
+
return json_response['policy']
|
787
|
+
rescue RestClient::Exception => e
|
788
|
+
if e.response && e.response.code == 404
|
789
|
+
print_red_alert "Policy not found by id #{id}"
|
790
|
+
return nil
|
791
|
+
else
|
792
|
+
raise e
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
797
|
+
def find_policy_by_name(name)
|
798
|
+
json_response = @policies_interface.list({name: name.to_s})
|
799
|
+
policies = json_response['policies']
|
800
|
+
if policies.empty?
|
801
|
+
print_red_alert "Policy not found by name #{name}"
|
802
|
+
return nil
|
803
|
+
elsif policies.size > 1
|
804
|
+
print_red_alert "#{policies.size} policies found by name #{name}"
|
805
|
+
# print_policies_table(policies, {color: red})
|
806
|
+
rows = policies.collect do |policy|
|
807
|
+
{id: policy['id'], name: policy['name']}
|
808
|
+
end
|
809
|
+
print red
|
810
|
+
tp rows, [:id, :name]
|
811
|
+
print reset,"\n"
|
812
|
+
return nil
|
813
|
+
else
|
814
|
+
policy = policies[0]
|
815
|
+
# merge in tenants map
|
816
|
+
if json_response['tenants'] && json_response['tenants'][policy['id']]
|
817
|
+
policy['tenants'] = json_response['tenants'][policy['id']]
|
818
|
+
end
|
819
|
+
return policy
|
820
|
+
end
|
821
|
+
end
|
822
|
+
|
823
|
+
def find_policy_type_by_id(id)
|
824
|
+
begin
|
825
|
+
json_response = @policies_interface.get_type(id.to_s)
|
826
|
+
return json_response['policyType']
|
827
|
+
rescue RestClient::Exception => e
|
828
|
+
if e.response && e.response.code == 404
|
829
|
+
print_red_alert "Policy Type not found by id #{id}"
|
830
|
+
return nil
|
831
|
+
else
|
832
|
+
raise e
|
833
|
+
end
|
834
|
+
end
|
835
|
+
end
|
836
|
+
|
837
|
+
def format_tenants(accounts)
|
838
|
+
if accounts && accounts.size > 0
|
839
|
+
account_ids = accounts.collect {|it| it['id'] }.uniq
|
840
|
+
account_names = accounts.collect {|it| it['name'] }.uniq
|
841
|
+
"(#{account_ids.join(',')}) #{account_names.join(',')}"
|
842
|
+
else
|
843
|
+
""
|
844
|
+
end
|
845
|
+
end
|
846
|
+
|
847
|
+
end
|