morpheus-cli 3.1.1.2 → 3.1.2
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 +3 -11
- data/lib/morpheus/api/storage_providers_interface.rb +47 -0
- data/lib/morpheus/cli.rb +1 -0
- data/lib/morpheus/cli/archives_command.rb +8 -6
- data/lib/morpheus/cli/mixins/print_helper.rb +19 -3
- data/lib/morpheus/cli/storage_providers_command.rb +586 -0
- data/lib/morpheus/cli/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41e5e60229896649507f3df02222124865c803ff
|
4
|
+
data.tar.gz: c4eef70518c898cf317d99c3148bbbb0b57af624
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 673e4e27f7a0dc245ead08bb40bf4f7ab67c5a73c4ac81d283c29659b66fe1a7b932c6bc62ea1e417ee3b4317e34d6117c98dc6d3958e67fab0ef292e45d3d38
|
7
|
+
data.tar.gz: 74b88bc851e272d82a46f2f8341b335c74cecdc5c6ada550bd8b973bd4a2fb6a0aa3dfb83a7092e1c4a138457f1ef874b32a4d1c58e94ae06fe0bc854d8385bd
|
@@ -243,16 +243,8 @@ class Morpheus::APIClient
|
|
243
243
|
Morpheus::ImageBuilderInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
|
244
244
|
end
|
245
245
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
# def preseed_scripts
|
251
|
-
# Morpheus::PreseedScriptsInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
|
252
|
-
# end
|
253
|
-
|
254
|
-
# def boot_scripts
|
255
|
-
# Morpheus::BootScriptsInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
|
256
|
-
# end
|
246
|
+
def storage_providers
|
247
|
+
Morpheus::StorageProvidersInterface.new(@access_token, @refresh_token, @expires_at, @base_url)
|
248
|
+
end
|
257
249
|
|
258
250
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'morpheus/api/api_client'
|
2
|
+
|
3
|
+
class Morpheus::StorageProvidersInterface < Morpheus::APIClient
|
4
|
+
def initialize(access_token, refresh_token,expires_at = nil, base_url=nil)
|
5
|
+
@access_token = access_token
|
6
|
+
@refresh_token = refresh_token
|
7
|
+
@base_url = base_url
|
8
|
+
@expires_at = expires_at
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(id, params={})
|
12
|
+
raise "#{self.class}.get() passed a blank id!" if id.to_s == ''
|
13
|
+
url = "#{@base_url}/api/storage/providers/#{id}"
|
14
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
15
|
+
opts = {method: :get, url: url, headers: headers}
|
16
|
+
execute(opts)
|
17
|
+
end
|
18
|
+
|
19
|
+
def list(params={})
|
20
|
+
url = "#{@base_url}/api/storage/providers"
|
21
|
+
headers = { params: params, authorization: "Bearer #{@access_token}" }
|
22
|
+
opts = {method: :get, url: url, headers: headers}
|
23
|
+
execute(opts)
|
24
|
+
end
|
25
|
+
|
26
|
+
def create(payload)
|
27
|
+
url = "#{@base_url}/api/storage/providers"
|
28
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
29
|
+
opts = {method: :post, url: url, headers: headers, payload: payload.to_json}
|
30
|
+
execute(opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
def update(id, payload)
|
34
|
+
url = "#{@base_url}/api/storage/providers/#{id}"
|
35
|
+
headers = { :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
36
|
+
opts = {method: :put, url: url, headers: headers, payload: payload.to_json}
|
37
|
+
execute(opts)
|
38
|
+
end
|
39
|
+
|
40
|
+
def destroy(id, params={})
|
41
|
+
url = "#{@base_url}/api/storage/providers/#{id}"
|
42
|
+
headers = { :params => params, :authorization => "Bearer #{@access_token}", 'Content-Type' => 'application/json' }
|
43
|
+
opts = {method: :delete, url: url, timeout: 30, headers: headers}
|
44
|
+
execute(opts)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/morpheus/cli.rb
CHANGED
@@ -106,6 +106,7 @@ module Morpheus
|
|
106
106
|
load 'morpheus/cli/preseed_scripts_command.rb'
|
107
107
|
load 'morpheus/cli/boot_scripts_command.rb'
|
108
108
|
load 'morpheus/cli/archives_command.rb'
|
109
|
+
load 'morpheus/cli/storage_providers_command.rb'
|
109
110
|
|
110
111
|
# nice to have commands
|
111
112
|
load 'morpheus/cli/curl_command.rb'
|
@@ -560,12 +560,13 @@ class Morpheus::Cli::ArchivesCommand
|
|
560
560
|
end
|
561
561
|
|
562
562
|
if options[:dry_run]
|
563
|
-
print_h1 "DRY RUN"
|
563
|
+
# print_h1 "DRY RUN"
|
564
564
|
print "\n",cyan, bold, "Uploading #{upload_file_list.size} Files...", reset, "\n"
|
565
565
|
upload_file_list.each do |obj|
|
566
566
|
file, destination = obj[:file], obj[:destination]
|
567
|
-
#
|
568
|
-
|
567
|
+
#print cyan,bold, " - Uploading #{file} to #{bucket_id}:#{destination} DRY RUN", reset, "\n"
|
568
|
+
print_dry_run @archive_buckets_interface.dry.upload_file(bucket_id, file, destination)
|
569
|
+
print "\n"
|
569
570
|
end
|
570
571
|
return 0
|
571
572
|
end
|
@@ -621,9 +622,10 @@ class Morpheus::Cli::ArchivesCommand
|
|
621
622
|
end
|
622
623
|
|
623
624
|
if options[:dry_run]
|
624
|
-
|
625
|
-
#
|
626
|
-
|
625
|
+
#print cyan,bold, " - Uploading #{file} to #{bucket_id}:#{destination} DRY RUN", reset, "\n"
|
626
|
+
# print_h1 "DRY RUN"
|
627
|
+
print_dry_run @archive_buckets_interface.dry.upload_file(bucket_id, file, destination)
|
628
|
+
print "\n"
|
627
629
|
return 0
|
628
630
|
end
|
629
631
|
|
@@ -123,9 +123,25 @@ module Morpheus::Cli::PrintHelper
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
print "\n"
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
if opts[:headers] && opts[:headers]['Content-Type'] == 'application/json'
|
127
|
+
print "JSON: ", "\n"
|
128
|
+
print reset
|
129
|
+
print JSON.pretty_generate(payload)
|
130
|
+
else
|
131
|
+
print "Content-Type: #{opts[:headers]['Content-Type']}", "\n"
|
132
|
+
#print "BODY: ", "\n"
|
133
|
+
print reset
|
134
|
+
if payload.is_a?(File)
|
135
|
+
# pretty_size = Filesize.from("#{payload.size} B").pretty.strip
|
136
|
+
pretty_size = "#{payload.size} B"
|
137
|
+
# print "File: #{payload.path} (#{payload.size} bytes)"
|
138
|
+
print "File: #{payload.path} (#{pretty_size})"
|
139
|
+
elsif payload.is_a?(String)
|
140
|
+
print payload
|
141
|
+
else
|
142
|
+
print payload.inspect
|
143
|
+
end
|
144
|
+
end
|
129
145
|
end
|
130
146
|
print "\n"
|
131
147
|
print reset
|
@@ -0,0 +1,586 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'optparse'
|
3
|
+
require 'filesize'
|
4
|
+
require 'table_print'
|
5
|
+
require 'morpheus/cli/cli_command'
|
6
|
+
require 'morpheus/cli/mixins/infrastructure_helper'
|
7
|
+
|
8
|
+
class Morpheus::Cli::StorageProvidersCommand
|
9
|
+
include Morpheus::Cli::CliCommand
|
10
|
+
include Morpheus::Cli::InfrastructureHelper
|
11
|
+
|
12
|
+
set_command_name :'storage-providers'
|
13
|
+
|
14
|
+
register_subcommands :list, :get, :add, :update, :remove
|
15
|
+
|
16
|
+
# set_default_subcommand :list
|
17
|
+
|
18
|
+
def initialize()
|
19
|
+
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
20
|
+
end
|
21
|
+
|
22
|
+
def connect(opts)
|
23
|
+
@api_client = establish_remote_appliance_connection(opts)
|
24
|
+
@storage_providers_interface = @api_client.storage_providers
|
25
|
+
@clouds_interface = @api_client.clouds
|
26
|
+
@options_interface = @api_client.options
|
27
|
+
end
|
28
|
+
|
29
|
+
def handle(args)
|
30
|
+
handle_subcommand(args)
|
31
|
+
end
|
32
|
+
|
33
|
+
def list(args)
|
34
|
+
options = {}
|
35
|
+
params = {}
|
36
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
37
|
+
opts.banner = subcommand_usage()
|
38
|
+
build_common_options(opts, options, [:list, :json, :yaml, :csv, :fields, :json, :dry_run, :remote])
|
39
|
+
opts.footer = "List storage providers."
|
40
|
+
end
|
41
|
+
optparse.parse!(args)
|
42
|
+
connect(options)
|
43
|
+
begin
|
44
|
+
[:phrase, :offset, :max, :sort, :direction].each do |k|
|
45
|
+
params[k] = options[k] unless options[k].nil?
|
46
|
+
end
|
47
|
+
if options[:dry_run]
|
48
|
+
print_dry_run @storage_providers_interface.dry.list(params)
|
49
|
+
return
|
50
|
+
end
|
51
|
+
json_response = @storage_providers_interface.list(params)
|
52
|
+
storage_providers = json_response["storageProviders"]
|
53
|
+
if options[:include_fields]
|
54
|
+
json_response = {"storageProviders" => filter_data(storage_providers, options[:include_fields]) }
|
55
|
+
end
|
56
|
+
if options[:json]
|
57
|
+
puts as_json(json_response, options)
|
58
|
+
return 0
|
59
|
+
elsif options[:yaml]
|
60
|
+
puts as_yaml(json_response, options)
|
61
|
+
return 0
|
62
|
+
elsif options[:csv]
|
63
|
+
puts records_as_csv(storage_providers, options)
|
64
|
+
return 0
|
65
|
+
end
|
66
|
+
title = "Morpheus Storage Providers"
|
67
|
+
subtitles = []
|
68
|
+
if params[:phrase]
|
69
|
+
subtitles << "Search: #{params[:phrase]}".strip
|
70
|
+
end
|
71
|
+
print_h1 title, subtitles
|
72
|
+
if storage_providers.empty?
|
73
|
+
print cyan,"No storage providers found.",reset,"\n"
|
74
|
+
else
|
75
|
+
rows = storage_providers.collect {|storage_provider|
|
76
|
+
row = {
|
77
|
+
id: storage_provider['id'],
|
78
|
+
name: storage_provider['name'],
|
79
|
+
provider: format_storage_provider_type(storage_provider),
|
80
|
+
bucket: format_bucket_name(storage_provider),
|
81
|
+
backups: storage_provider['defaultBackupTarget'] ? 'Yes' : 'No',
|
82
|
+
deployments: storage_provider['defaultDeploymentTarget'] ? 'Yes' : 'No',
|
83
|
+
virtualImages: storage_provider['defaultVirtualImageTarget'] ? 'Yes' : 'No',
|
84
|
+
}
|
85
|
+
row
|
86
|
+
}
|
87
|
+
columns = [:id, :name, {:provider => {:display_name => "Provider Type".upcase} }, {:bucket => {:display_name => "Bucket Name".upcase} }, :backups, :deployments]
|
88
|
+
if options[:include_fields]
|
89
|
+
columns = options[:include_fields]
|
90
|
+
rows = storage_providers
|
91
|
+
end
|
92
|
+
print cyan
|
93
|
+
print as_pretty_table(rows, columns, options)
|
94
|
+
print reset
|
95
|
+
print_results_pagination(json_response, {:label => "storage provider", :n_label => "storage providers"})
|
96
|
+
end
|
97
|
+
print reset,"\n"
|
98
|
+
return 0
|
99
|
+
rescue RestClient::Exception => e
|
100
|
+
print_rest_exception(e, options)
|
101
|
+
exit 1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def get(args)
|
106
|
+
options = {}
|
107
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
108
|
+
opts.banner = subcommand_usage("[storage-provider]")
|
109
|
+
build_common_options(opts, options, [:json, :yaml, :csv, :fields, :dry_run, :remote])
|
110
|
+
opts.footer = "Get details about a storage provider." + "\n" +
|
111
|
+
"[storage-provider] is required. This is the name or id of a storage provider."
|
112
|
+
end
|
113
|
+
optparse.parse!(args)
|
114
|
+
if args.count != 1
|
115
|
+
print_error Morpheus::Terminal.angry_prompt
|
116
|
+
puts_error "#{command_name} missing argument: [storage-provider]\n#{optparse}"
|
117
|
+
return 1
|
118
|
+
end
|
119
|
+
connect(options)
|
120
|
+
begin
|
121
|
+
if options[:dry_run]
|
122
|
+
if args[0].to_s =~ /\A\d{1,}\Z/
|
123
|
+
print_dry_run @storage_providers_interface.dry.get(args[0].to_i)
|
124
|
+
else
|
125
|
+
print_dry_run @storage_providers_interface.dry.list({name:args[0]})
|
126
|
+
end
|
127
|
+
return
|
128
|
+
end
|
129
|
+
storage_provider = find_storage_provider_by_name_or_id(args[0])
|
130
|
+
return 1 if storage_provider.nil?
|
131
|
+
json_response = {'storageProvider' => storage_provider} # skip redundant request
|
132
|
+
# json_response = @storage_providers_interface.get(storage_provider['id'])
|
133
|
+
storage_provider = json_response['storageProvider']
|
134
|
+
if options[:include_fields]
|
135
|
+
json_response = {'storageProvider' => filter_data(storage_provider, options[:include_fields]) }
|
136
|
+
end
|
137
|
+
if options[:json]
|
138
|
+
puts as_json(json_response, options)
|
139
|
+
return 0
|
140
|
+
elsif options[:yaml]
|
141
|
+
puts as_yaml(json_response, options)
|
142
|
+
return 0
|
143
|
+
elsif options[:csv]
|
144
|
+
puts records_as_csv([storage_provider], options)
|
145
|
+
return 0
|
146
|
+
end
|
147
|
+
print_h1 "Storage Provider Details"
|
148
|
+
print cyan
|
149
|
+
description_cols = {
|
150
|
+
"ID" => 'id',
|
151
|
+
"Name" => lambda {|it| it['name'] },
|
152
|
+
"Provider Type" => lambda {|it| format_storage_provider_type(it) },
|
153
|
+
"Bucket Name" => lambda {|it| format_bucket_name(it) },
|
154
|
+
"Default Backup Target" => lambda {|it| it['defaultBackupTarget'] ? 'Yes' : 'No' },
|
155
|
+
"Default Deployment Target" => lambda {|it| it['defaultDeploymentTarget'] ? 'Yes' : 'No' },
|
156
|
+
"Default Virtual Image Store" => lambda {|it| it['defaultVirtualImageTarget'] ? 'Yes' : 'No' },
|
157
|
+
"Archive Snapshots" => lambda {|it| it['copyToStore'] ? 'Yes' : 'No' }
|
158
|
+
}
|
159
|
+
print_description_list(description_cols, storage_provider)
|
160
|
+
print reset,"\n"
|
161
|
+
return 0
|
162
|
+
rescue RestClient::Exception => e
|
163
|
+
print_rest_exception(e, options)
|
164
|
+
return 1
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def add(args)
|
169
|
+
options = {}
|
170
|
+
ip_range_list = nil
|
171
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
172
|
+
opts.banner = subcommand_usage()
|
173
|
+
opts.on('--name VALUE', String, "Name for this storage provider") do |val|
|
174
|
+
options['name'] = val
|
175
|
+
end
|
176
|
+
opts.on('--type code', String, "Storage Provider Type Code") do |val|
|
177
|
+
options['providerType'] = val
|
178
|
+
end
|
179
|
+
opts.on('--bucket-name VALUE', String, "Bucket Name") do |val|
|
180
|
+
options['bucketName'] = val
|
181
|
+
end
|
182
|
+
opts.on('--default-backup-target [on|off]', String, "Default Backup Target") do |val|
|
183
|
+
options['defaultBackupTarget'] = val.to_s == 'on' || val.to_s == 'true'
|
184
|
+
end
|
185
|
+
opts.on('--default-deployment-target [on|off]', String, "Default Deployment Target") do |val|
|
186
|
+
options['defaultDeploymentTarget'] = val.to_s == 'on' || val.to_s == 'true'
|
187
|
+
end
|
188
|
+
opts.on('--default-virtual-image-target [on|off]', String, "Default Virtual Image Store") do |val|
|
189
|
+
options['defaultVirtualImageTarget'] = val.to_s == 'on' || val.to_s == 'true'
|
190
|
+
end
|
191
|
+
opts.on('--copy-to-store [on|off]', String, "Archive Snapshots") do |val|
|
192
|
+
options['copyToStore'] = val.to_s == 'on' || val.to_s == 'true'
|
193
|
+
end
|
194
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :quiet, :remote])
|
195
|
+
opts.footer = "Create a new storage provider." + "\n" +
|
196
|
+
"[name] is required and can be passed as --name instead."
|
197
|
+
end
|
198
|
+
optparse.parse!(args)
|
199
|
+
if args.count > 1
|
200
|
+
print_error Morpheus::Terminal.angry_prompt
|
201
|
+
puts_error "wrong number of arguments, expected 0-1 and got #{args.count}\n#{optparse}"
|
202
|
+
return 1
|
203
|
+
end
|
204
|
+
connect(options)
|
205
|
+
begin
|
206
|
+
# merge -O options into normally parsed options
|
207
|
+
options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
208
|
+
|
209
|
+
# support [name] as first argument
|
210
|
+
if args[0]
|
211
|
+
options['name'] = args[0]
|
212
|
+
end
|
213
|
+
|
214
|
+
# construct payload
|
215
|
+
payload = nil
|
216
|
+
if options[:payload]
|
217
|
+
payload = options[:payload]
|
218
|
+
else
|
219
|
+
# prompt for storage provider options
|
220
|
+
payload = {
|
221
|
+
'storageProvider' => {
|
222
|
+
# 'config' => {}
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
226
|
+
# allow arbitrary -O options
|
227
|
+
payload['storageProvider'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
228
|
+
|
229
|
+
# Name
|
230
|
+
if options['name']
|
231
|
+
payload['storageProvider']['name'] = options['name']
|
232
|
+
else
|
233
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'description' => 'Name for this storage provider.'}], options)
|
234
|
+
payload['storageProvider']['name'] = v_prompt['name']
|
235
|
+
end
|
236
|
+
|
237
|
+
# Storage Provider Type
|
238
|
+
storage_provider_type_code = nil
|
239
|
+
if options['type']
|
240
|
+
storage_provider_type_code = options['type'].to_s
|
241
|
+
elsif options['providerType']
|
242
|
+
storage_provider_type_code = options['providerType'].to_s
|
243
|
+
else
|
244
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'providerType', 'fieldLabel' => 'Provider Type', 'type' => 'select', 'selectOptions' => get_storage_provider_types(), 'required' => true, 'description' => 'Choose a storage provider type.'}], options, @api_client, {})
|
245
|
+
storage_provider_type_code = v_prompt['providerType'] unless v_prompt['providerType'].nil?
|
246
|
+
end
|
247
|
+
payload['storageProvider']['providerType'] = storage_provider_type_code
|
248
|
+
|
249
|
+
# Provider Type Specific Options
|
250
|
+
provider_type_option_types = nil
|
251
|
+
if storage_provider_type_code == 's3'
|
252
|
+
# print_h2 "Amazon S3 Options"
|
253
|
+
provider_type_option_types = [
|
254
|
+
{'fieldContext' => 'config', 'fieldName' => 'accessKey', 'fieldLabel' => 'Access Key', 'type' => 'text', 'required' => true, 'description' => ''},
|
255
|
+
{'fieldContext' => 'config', 'fieldName' => 'secretKey', 'fieldLabel' => 'Secret Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
256
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
257
|
+
{'fieldContext' => 'config', 'fieldName' => 'endpoint', 'fieldLabel' => 'Endpoint URL', 'type' => 'text', 'required' => false, 'description' => 'Optional endpoint URL if pointing to an object store other than amazon that mimics the Amazon S3 APIs.'},
|
258
|
+
]
|
259
|
+
elsif storage_provider_type_code == 'azure'
|
260
|
+
# print_h2 "Azure Options"
|
261
|
+
provider_type_option_types = [
|
262
|
+
{'fieldContext' => 'config', 'fieldName' => 'storageAccount', 'fieldLabel' => 'Storage Account', 'type' => 'text', 'required' => true, 'description' => ''},
|
263
|
+
{'fieldContext' => 'config', 'fieldName' => 'storageKey', 'fieldLabel' => 'Storage Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
264
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''}
|
265
|
+
]
|
266
|
+
elsif storage_provider_type_code == 'cifs'
|
267
|
+
# print_h2 "CIFS Options"
|
268
|
+
provider_type_option_types = [
|
269
|
+
{'fieldContext' => 'config', 'fieldName' => 'host', 'fieldLabel' => 'Host', 'type' => 'text', 'required' => true, 'description' => ''},
|
270
|
+
{'fieldContext' => 'config', 'fieldName' => 'username', 'fieldLabel' => 'Username', 'type' => 'text', 'required' => true, 'description' => ''},
|
271
|
+
{'fieldContext' => 'config', 'fieldName' => 'password', 'fieldLabel' => 'Password', 'type' => 'password', 'required' => true, 'description' => ''},
|
272
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''}
|
273
|
+
]
|
274
|
+
elsif storage_provider_type_code == 'local'
|
275
|
+
# print_h2 "Local Storage Options"
|
276
|
+
provider_type_option_types = [
|
277
|
+
{'fieldContext' => 'config', 'fieldName' => 'basePath', 'fieldLabel' => 'Storage Path', 'type' => 'text', 'required' => true, 'description' => ''},
|
278
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'hidden', 'required' => true, 'description' => '', 'defaultValue' => '.'}
|
279
|
+
]
|
280
|
+
elsif storage_provider_type_code == 'nfs'
|
281
|
+
# print_h2 "NFSv3 Options"
|
282
|
+
provider_type_option_types = [
|
283
|
+
{'fieldContext' => 'config', 'fieldName' => 'host', 'fieldLabel' => 'Host', 'type' => 'text', 'required' => true, 'description' => ''},
|
284
|
+
{'fieldContext' => 'config', 'fieldName' => 'exportFolder', 'fieldLabel' => 'Export Folder', 'type' => 'text', 'required' => false, 'description' => ''},
|
285
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'hidden', 'required' => true, 'description' => '', 'defaultValue' => '/'}
|
286
|
+
]
|
287
|
+
elsif storage_provider_type_code == 'openstack'
|
288
|
+
# print_h2 "Openstack Swift Options"
|
289
|
+
provider_type_option_types = [
|
290
|
+
{'fieldContext' => 'config', 'fieldName' => 'username', 'fieldLabel' => 'Username', 'type' => 'text', 'required' => true, 'description' => ''},
|
291
|
+
{'fieldContext' => 'config', 'fieldName' => 'apiKey', 'fieldLabel' => 'API Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
292
|
+
{'fieldContext' => 'config', 'fieldName' => 'region', 'fieldLabel' => 'Region', 'type' => 'text', 'required' => true, 'description' => ''},
|
293
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
294
|
+
{'fieldContext' => 'config', 'fieldName' => 'identityUrl', 'fieldLabel' => 'Identity URL', 'type' => 'text', 'required' => true, 'description' => ''},
|
295
|
+
]
|
296
|
+
elsif storage_provider_type_code == 'rackspace'
|
297
|
+
# print_h2 "Rackspace CDN Options"
|
298
|
+
provider_type_option_types = [
|
299
|
+
{'fieldContext' => 'config', 'fieldName' => 'accessKey', 'fieldLabel' => 'Access Key', 'type' => 'text', 'required' => true, 'description' => ''},
|
300
|
+
{'fieldContext' => 'config', 'fieldName' => 'secretKey', 'fieldLabel' => 'Secret Key', 'type' => 'password', 'required' => true, 'description' => ''},
|
301
|
+
{'fieldName' => 'bucketName', 'fieldLabel' => 'Bucket Name', 'type' => 'text', 'required' => true, 'description' => ''},
|
302
|
+
{'fieldContext' => 'config', 'fieldName' => 'endpoint', 'fieldLabel' => 'Endpoint URL', 'type' => 'text', 'required' => true, 'description' => 'Optional endpoint URL if pointing to an object store other than amazon that mimics the Amazon S3 APIs.'},
|
303
|
+
]
|
304
|
+
else
|
305
|
+
puts "warning: unrecognized storage provider type: '#{storage_provider_type_code}'"
|
306
|
+
end
|
307
|
+
if provider_type_option_types
|
308
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(provider_type_option_types, options, @api_client, {})
|
309
|
+
payload['storageProvider'].deep_merge!(v_prompt)
|
310
|
+
end
|
311
|
+
|
312
|
+
# Default Backup Target
|
313
|
+
if options['defaultBackupTarget'] != nil
|
314
|
+
payload['storageProvider']['defaultBackupTarget'] = options['defaultBackupTarget']
|
315
|
+
else
|
316
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultBackupTarget', 'fieldLabel' => 'Default Backup Target', 'type' => 'checkbox', 'required' => false, 'description' => '', 'defaultValue' => 'off'}], options)
|
317
|
+
payload['storageProvider']['defaultBackupTarget'] = (v_prompt['defaultBackupTarget'].to_s == 'on') unless v_prompt['defaultBackupTarget'].nil?
|
318
|
+
end
|
319
|
+
|
320
|
+
# Archive Snapshots
|
321
|
+
if options['copyToStore'] != nil
|
322
|
+
payload['storageProvider']['copyToStore'] = options['copyToStore']
|
323
|
+
else
|
324
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'copyToStore', 'fieldLabel' => 'Archive Snapshots', 'type' => 'checkbox', 'required' => false, 'description' => '', 'defaultValue' => 'on'}], options)
|
325
|
+
payload['storageProvider']['copyToStore'] = (v_prompt['copyToStore'].to_s == 'on') unless v_prompt['copyToStore'].nil?
|
326
|
+
end
|
327
|
+
|
328
|
+
# Default Deployment Target
|
329
|
+
if options['defaultDeploymentTarget'] != nil
|
330
|
+
payload['storageProvider']['defaultDeploymentTarget'] = options['defaultDeploymentTarget']
|
331
|
+
else
|
332
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultDeploymentTarget', 'fieldLabel' => 'Default Deployment Target', 'type' => 'checkbox', 'required' => false, 'description' => '', 'defaultValue' => 'off'}], options)
|
333
|
+
payload['storageProvider']['defaultDeploymentTarget'] = (v_prompt['defaultDeploymentTarget'].to_s == 'on') unless v_prompt['defaultDeploymentTarget'].nil?
|
334
|
+
end
|
335
|
+
|
336
|
+
# Default Virtual Image Store
|
337
|
+
if options['defaultVirtualImageTarget'] != nil
|
338
|
+
payload['storageProvider']['defaultVirtualImageTarget'] = options['defaultVirtualImageTarget']
|
339
|
+
else
|
340
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'defaultVirtualImageTarget', 'fieldLabel' => 'Default Virtual Image Store', 'type' => 'checkbox', 'required' => false, 'description' => '', 'defaultValue' => 'off'}], options)
|
341
|
+
payload['storageProvider']['defaultVirtualImageTarget'] = (v_prompt['defaultVirtualImageTarget'].to_s == 'on') unless v_prompt['defaultVirtualImageTarget'].nil?
|
342
|
+
end
|
343
|
+
|
344
|
+
end
|
345
|
+
|
346
|
+
|
347
|
+
if options[:dry_run]
|
348
|
+
print_dry_run @storage_providers_interface.dry.create(payload)
|
349
|
+
return
|
350
|
+
end
|
351
|
+
json_response = @storage_providers_interface.create(payload)
|
352
|
+
if options[:json]
|
353
|
+
print JSON.pretty_generate(json_response)
|
354
|
+
print "\n"
|
355
|
+
elsif !options[:quiet]
|
356
|
+
storage_provider = json_response['storageProvider']
|
357
|
+
print_green_success "Added storage provider #{storage_provider['name']}"
|
358
|
+
get([storage_provider['id']])
|
359
|
+
end
|
360
|
+
return 0
|
361
|
+
rescue RestClient::Exception => e
|
362
|
+
print_rest_exception(e, options)
|
363
|
+
exit 1
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def update(args)
|
368
|
+
options = {}
|
369
|
+
ip_range_list = nil
|
370
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
371
|
+
opts.banner = subcommand_usage("[storage-provider] [options]")
|
372
|
+
opts.on('--name VALUE', String, "Name for this storage provider") do |val|
|
373
|
+
options['name'] = val
|
374
|
+
end
|
375
|
+
opts.on('--type code', String, "Storage Provider Type Code") do |val|
|
376
|
+
options['providerType'] = val
|
377
|
+
end
|
378
|
+
opts.on('--bucket-name VALUE', String, "Bucket Name") do |val|
|
379
|
+
options['bucketName'] = val
|
380
|
+
end
|
381
|
+
opts.on('--default-backup-target [on|off]', String, "Default Backup Target") do |val|
|
382
|
+
options['defaultBackupTarget'] = val.to_s == 'on' || val.to_s == 'true'
|
383
|
+
end
|
384
|
+
opts.on('--default-deployment-target [on|off]', String, "Default Deployment Target") do |val|
|
385
|
+
options['defaultDeploymentTarget'] = val.to_s == 'on' || val.to_s == 'true'
|
386
|
+
end
|
387
|
+
opts.on('--default-virtual-image-target [on|off]', String, "Default Virtual Image Store") do |val|
|
388
|
+
options['defaultVirtualImageTarget'] = val.to_s == 'on' || val.to_s == 'true'
|
389
|
+
end
|
390
|
+
opts.on('--copy-to-store [on|off]', String, "Archive Snapshots") do |val|
|
391
|
+
options['copyToStore'] = val.to_s == 'on' || val.to_s == 'true'
|
392
|
+
end
|
393
|
+
build_common_options(opts, options, [:options, :payload, :json, :dry_run, :remote])
|
394
|
+
opts.footer = "Update a storage provider." + "\n" +
|
395
|
+
"[storage-provider] is required. This is the id of a storage provider."
|
396
|
+
end
|
397
|
+
optparse.parse!(args)
|
398
|
+
if args.count != 1
|
399
|
+
print_error Morpheus::Terminal.angry_prompt
|
400
|
+
puts_error "wrong number of arguments, expected 1 and got #{args.count}\n#{optparse}"
|
401
|
+
return 1
|
402
|
+
end
|
403
|
+
connect(options)
|
404
|
+
|
405
|
+
begin
|
406
|
+
storage_provider = find_storage_provider_by_name_or_id(args[0])
|
407
|
+
return 1 if storage_provider.nil?
|
408
|
+
|
409
|
+
# merge -O options into normally parsed options
|
410
|
+
options.deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
411
|
+
|
412
|
+
# construct payload
|
413
|
+
payload = nil
|
414
|
+
if options[:payload]
|
415
|
+
payload = options[:payload]
|
416
|
+
else
|
417
|
+
# prompt for storage provider options
|
418
|
+
# preserve previous config settings
|
419
|
+
payload = {
|
420
|
+
'storageProvider' => {
|
421
|
+
'config' => storage_provider['config']
|
422
|
+
}
|
423
|
+
}
|
424
|
+
|
425
|
+
# allow arbitrary -O options
|
426
|
+
payload['storageProvider'].deep_merge!(options[:options].reject {|k,v| k.is_a?(Symbol) }) if options[:options]
|
427
|
+
|
428
|
+
# Name
|
429
|
+
if options['name']
|
430
|
+
payload['storageProvider']['name'] = options['name']
|
431
|
+
end
|
432
|
+
|
433
|
+
# Default Backup Target
|
434
|
+
if options['defaultBackupTarget'] != nil
|
435
|
+
payload['storageProvider']['defaultBackupTarget'] = options['defaultBackupTarget']
|
436
|
+
end
|
437
|
+
|
438
|
+
# Archive Snapshots
|
439
|
+
if options['copyToStore'] != nil
|
440
|
+
payload['storageProvider']['copyToStore'] = options['copyToStore']
|
441
|
+
end
|
442
|
+
|
443
|
+
# Default Deployment Target
|
444
|
+
if options['defaultDeploymentTarget'] != nil
|
445
|
+
payload['storageProvider']['defaultDeploymentTarget'] = options['defaultDeploymentTarget']
|
446
|
+
end
|
447
|
+
|
448
|
+
# Default Virtual Image Store
|
449
|
+
if options['defaultVirtualImageTarget'] != nil
|
450
|
+
payload['storageProvider']['defaultVirtualImageTarget'] = options['defaultVirtualImageTarget']
|
451
|
+
end
|
452
|
+
|
453
|
+
end
|
454
|
+
|
455
|
+
if options[:dry_run]
|
456
|
+
print_dry_run @storage_providers_interface.dry.update(storage_provider["id"], payload)
|
457
|
+
return
|
458
|
+
end
|
459
|
+
json_response = @storage_providers_interface.update(storage_provider["id"], payload)
|
460
|
+
if options[:json]
|
461
|
+
puts as_json(json_response)
|
462
|
+
else
|
463
|
+
storage_provider = json_response['storageProvider']
|
464
|
+
print_green_success "Updated storage provider #{storage_provider['name']}"
|
465
|
+
get([storage_provider['id']])
|
466
|
+
end
|
467
|
+
return 0
|
468
|
+
rescue RestClient::Exception => e
|
469
|
+
print_rest_exception(e, options)
|
470
|
+
return 1
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
def remove(args)
|
475
|
+
options = {}
|
476
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
477
|
+
opts.banner = subcommand_usage("[storage-provider]")
|
478
|
+
build_common_options(opts, options, [:account, :auto_confirm, :json, :dry_run, :remote])
|
479
|
+
opts.footer = "Delete a storage provider." + "\n" +
|
480
|
+
"[storage-provider] is required. This is the name or id of a storage provider."
|
481
|
+
end
|
482
|
+
optparse.parse!(args)
|
483
|
+
|
484
|
+
if args.count < 1
|
485
|
+
print_error Morpheus::Terminal.angry_prompt
|
486
|
+
puts_error "#{command_name} missing argument: [storage-provider]\n#{optparse}"
|
487
|
+
return 1
|
488
|
+
end
|
489
|
+
|
490
|
+
connect(options)
|
491
|
+
begin
|
492
|
+
storage_provider = find_storage_provider_by_name_or_id(args[0])
|
493
|
+
return 1 if storage_provider.nil?
|
494
|
+
|
495
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to delete the storage provider: #{storage_provider['name']}?")
|
496
|
+
return 9, "aborted command"
|
497
|
+
end
|
498
|
+
if options[:dry_run]
|
499
|
+
print_dry_run @storage_providers_interface.dry.destroy(storage_provider['id'])
|
500
|
+
return 0
|
501
|
+
end
|
502
|
+
json_response = @storage_providers_interface.destroy(storage_provider['id'])
|
503
|
+
if options[:json]
|
504
|
+
print JSON.pretty_generate(json_response)
|
505
|
+
print "\n"
|
506
|
+
else
|
507
|
+
print_green_success "Removed storage provider #{storage_provider['name']}"
|
508
|
+
# list([])
|
509
|
+
end
|
510
|
+
return 0
|
511
|
+
rescue RestClient::Exception => e
|
512
|
+
print_rest_exception(e, options)
|
513
|
+
return 1
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
private
|
518
|
+
|
519
|
+
|
520
|
+
def get_storage_provider_types()
|
521
|
+
[
|
522
|
+
{'name' => 'Amazon S3', 'value' => 's3'},
|
523
|
+
{'name' => 'Azure', 'value' => 'azure'},
|
524
|
+
{'name' => 'CIFS', 'value' => 'cifs'},
|
525
|
+
{'name' => 'Local Storage', 'value' => 'local'},
|
526
|
+
{'name' => 'NFSv3', 'value' => 'nfs'},
|
527
|
+
{'name' => 'Openstack Swift', 'value' => 'openstack'},
|
528
|
+
{'name' => 'Rackspace CDN', 'value' => 'rackspace'}
|
529
|
+
]
|
530
|
+
end
|
531
|
+
|
532
|
+
def find_storage_provider_by_name_or_id(val)
|
533
|
+
if val.to_s =~ /\A\d{1,}\Z/
|
534
|
+
return find_storage_provider_by_id(val)
|
535
|
+
else
|
536
|
+
return find_storage_provider_by_name(val)
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
def find_storage_provider_by_id(id)
|
541
|
+
begin
|
542
|
+
json_response = @storage_providers_interface.get(id.to_i)
|
543
|
+
return json_response['storageProvider']
|
544
|
+
rescue RestClient::Exception => e
|
545
|
+
if e.response && e.response.code == 404
|
546
|
+
print_red_alert "Storage Provider not found by id #{id}"
|
547
|
+
return nil
|
548
|
+
else
|
549
|
+
raise e
|
550
|
+
end
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
def find_storage_provider_by_name(name)
|
555
|
+
json_response = @storage_providers_interface.list({name: name.to_s})
|
556
|
+
storage_providers = json_response['storageProviders']
|
557
|
+
if storage_providers.empty?
|
558
|
+
print_red_alert "Storage Provider not found by name #{name}"
|
559
|
+
return nil
|
560
|
+
elsif storage_providers.size > 1
|
561
|
+
print_red_alert "#{storage_providers.size} storage providers found by name #{name}"
|
562
|
+
rows = storage_providers.collect do |storage_provider|
|
563
|
+
{id: it['id'], name: it['name']}
|
564
|
+
end
|
565
|
+
print red
|
566
|
+
tp rows, [:id, :name]
|
567
|
+
print reset,"\n"
|
568
|
+
return nil
|
569
|
+
else
|
570
|
+
return storage_providers[0]
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
def format_bucket_name(storage_provider)
|
575
|
+
if storage_provider['providerType'] == 'local'
|
576
|
+
storage_provider['config'] ? storage_provider['config']['basePath'] : ''
|
577
|
+
else
|
578
|
+
storage_provider['bucketName']
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
def format_storage_provider_type(storage_provider)
|
583
|
+
storage_provider['providerType'].to_s.capitalize
|
584
|
+
end
|
585
|
+
|
586
|
+
end
|
data/lib/morpheus/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: morpheus-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Estes
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2017-12-
|
14
|
+
date: 2017-12-13 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: bundler
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- lib/morpheus/api/security_groups_interface.rb
|
191
191
|
- lib/morpheus/api/servers_interface.rb
|
192
192
|
- lib/morpheus/api/setup_interface.rb
|
193
|
+
- lib/morpheus/api/storage_providers_interface.rb
|
193
194
|
- lib/morpheus/api/task_sets_interface.rb
|
194
195
|
- lib/morpheus/api/tasks_interface.rb
|
195
196
|
- lib/morpheus/api/users_interface.rb
|
@@ -260,6 +261,7 @@ files:
|
|
260
261
|
- lib/morpheus/cli/shell.rb
|
261
262
|
- lib/morpheus/cli/source_command.rb
|
262
263
|
- lib/morpheus/cli/ssl_verification_command.rb
|
264
|
+
- lib/morpheus/cli/storage_providers_command.rb
|
263
265
|
- lib/morpheus/cli/tasks.rb
|
264
266
|
- lib/morpheus/cli/users.rb
|
265
267
|
- lib/morpheus/cli/version.rb
|