morpheus-cli 4.2.16 → 4.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +1 -1
- data/README.md +8 -6
- data/lib/morpheus/api/api_client.rb +32 -14
- data/lib/morpheus/api/auth_interface.rb +4 -2
- data/lib/morpheus/api/backup_jobs_interface.rb +9 -0
- data/lib/morpheus/api/backups_interface.rb +16 -0
- data/lib/morpheus/api/deploy_interface.rb +25 -56
- data/lib/morpheus/api/deployments_interface.rb +44 -55
- data/lib/morpheus/api/doc_interface.rb +57 -0
- data/lib/morpheus/api/instances_interface.rb +5 -0
- data/lib/morpheus/api/rest_interface.rb +40 -0
- data/lib/morpheus/api/user_sources_interface.rb +0 -15
- data/lib/morpheus/api/users_interface.rb +2 -3
- data/lib/morpheus/benchmarking.rb +2 -2
- data/lib/morpheus/cli.rb +4 -1
- data/lib/morpheus/cli/access_token_command.rb +27 -10
- data/lib/morpheus/cli/apps.rb +21 -15
- data/lib/morpheus/cli/backup_jobs_command.rb +276 -0
- data/lib/morpheus/cli/backups_command.rb +271 -0
- data/lib/morpheus/cli/blueprints_command.rb +27 -61
- data/lib/morpheus/cli/boot_scripts_command.rb +1 -1
- data/lib/morpheus/cli/budgets_command.rb +4 -4
- data/lib/morpheus/cli/cli_command.rb +99 -41
- data/lib/morpheus/cli/cloud_resource_pools_command.rb +16 -0
- data/lib/morpheus/cli/clouds.rb +7 -10
- data/lib/morpheus/cli/clusters.rb +0 -18
- data/lib/morpheus/cli/commands/standard/benchmark_command.rb +7 -7
- data/lib/morpheus/cli/commands/standard/man_command.rb +1 -1
- data/lib/morpheus/cli/credentials.rb +13 -9
- data/lib/morpheus/cli/deploy.rb +374 -0
- data/lib/morpheus/cli/deployments.rb +521 -197
- data/lib/morpheus/cli/deploys.rb +271 -126
- data/lib/morpheus/cli/doc.rb +182 -0
- data/lib/morpheus/cli/error_handler.rb +23 -8
- data/lib/morpheus/cli/errors.rb +3 -2
- data/lib/morpheus/cli/image_builder_command.rb +2 -2
- data/lib/morpheus/cli/instances.rb +136 -17
- data/lib/morpheus/cli/invoices_command.rb +59 -47
- data/lib/morpheus/cli/jobs_command.rb +2 -2
- data/lib/morpheus/cli/library_instance_types_command.rb +17 -3
- data/lib/morpheus/cli/library_layouts_command.rb +1 -1
- data/lib/morpheus/cli/login.rb +9 -3
- data/lib/morpheus/cli/mixins/accounts_helper.rb +158 -100
- data/lib/morpheus/cli/mixins/backups_helper.rb +115 -0
- data/lib/morpheus/cli/mixins/deployments_helper.rb +135 -0
- data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
- data/lib/morpheus/cli/mixins/print_helper.rb +110 -74
- data/lib/morpheus/cli/mixins/provisioning_helper.rb +2 -2
- data/lib/morpheus/cli/mixins/whoami_helper.rb +19 -6
- data/lib/morpheus/cli/network_routers_command.rb +1 -1
- data/lib/morpheus/cli/option_parser.rb +48 -5
- data/lib/morpheus/cli/option_types.rb +1 -1
- data/lib/morpheus/cli/projects_command.rb +7 -7
- data/lib/morpheus/cli/provisioning_licenses_command.rb +2 -2
- data/lib/morpheus/cli/remote.rb +3 -2
- data/lib/morpheus/cli/roles.rb +49 -92
- data/lib/morpheus/cli/security_groups.rb +7 -1
- data/lib/morpheus/cli/service_plans_command.rb +10 -10
- data/lib/morpheus/cli/setup.rb +1 -1
- data/lib/morpheus/cli/shell.rb +7 -6
- data/lib/morpheus/cli/subnets_command.rb +1 -1
- data/lib/morpheus/cli/tasks.rb +24 -10
- data/lib/morpheus/cli/tenants_command.rb +133 -163
- data/lib/morpheus/cli/user_groups_command.rb +20 -65
- data/lib/morpheus/cli/user_settings_command.rb +115 -13
- data/lib/morpheus/cli/user_sources_command.rb +57 -24
- data/lib/morpheus/cli/users.rb +210 -186
- data/lib/morpheus/cli/version.rb +1 -1
- data/lib/morpheus/cli/whitelabel_settings_command.rb +29 -5
- data/lib/morpheus/cli/whoami.rb +113 -6
- data/lib/morpheus/cli/workflows.rb +11 -8
- data/lib/morpheus/ext/hash.rb +21 -0
- data/lib/morpheus/terminal.rb +1 -0
- metadata +12 -3
- data/lib/morpheus/cli/auth_command.rb +0 -105
@@ -0,0 +1,374 @@
|
|
1
|
+
require 'morpheus/cli/cli_command'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
class Morpheus::Cli::Deploy
|
5
|
+
include Morpheus::Cli::CliCommand
|
6
|
+
include Morpheus::Cli::DeploymentsHelper
|
7
|
+
|
8
|
+
set_command_name :deploy
|
9
|
+
|
10
|
+
def connect(opts)
|
11
|
+
@api_client = establish_remote_appliance_connection(opts)
|
12
|
+
@instances_interface = @api_client.instances
|
13
|
+
@deploy_interface = @api_client.deploy
|
14
|
+
@deployments_interface = @api_client.deployments
|
15
|
+
end
|
16
|
+
|
17
|
+
def handle(args)
|
18
|
+
options={}
|
19
|
+
optparse = Morpheus::Cli::OptionParser.new do|opts|
|
20
|
+
opts.banner = "Usage: morpheus deploy [environment]"
|
21
|
+
build_common_options(opts, options, [:auto_confirm, :remote, :dry_run])
|
22
|
+
opts.footer = <<-EOT
|
23
|
+
Deploy to an instance using the morpheus.yml file, located in the working directory.
|
24
|
+
[environment] is optional. Merge settings under environments.{environment}. Default is no environment.
|
25
|
+
|
26
|
+
First this parses the morpheus.yml file and merges the specified environment settings.
|
27
|
+
The specified instance must exist and the specified version must not exist.
|
28
|
+
If the settings are valid, the new deployment version will be created and
|
29
|
+
all the specified files are uploaded to the new deployment version.
|
30
|
+
Finally, it deploys the new version to the instance.
|
31
|
+
|
32
|
+
The morpheus.yml should be located in the working directory.
|
33
|
+
This file contains the information necessary to perform a deployment via the cli.
|
34
|
+
|
35
|
+
File Settings
|
36
|
+
==================
|
37
|
+
|
38
|
+
* name - (required) The instance name we are deploying to and, by default, name of the deployment being created.
|
39
|
+
* version - (required) The version identifier of the deployment being created (userVersion)
|
40
|
+
* deployment - The name of the deployment being created, name is used by default
|
41
|
+
* script - The initial script to run before looking for files to upload.
|
42
|
+
* files - List of file patterns to use for uploading files and their target destination.
|
43
|
+
Each item should contain path and pattern, path may be relative to the working directory, default pattern is: '**/*'
|
44
|
+
* options - Map of deployment options depending on deployment type
|
45
|
+
* post_script - A post operation script to be run on the local machine
|
46
|
+
* stage_only - If set to true the deploy will only be staged and not actually run
|
47
|
+
* environments - Map of objects that contain nested properties for each environment name
|
48
|
+
|
49
|
+
It is possible to nest these properties in an "environments" map to override based on a passed environment.
|
50
|
+
|
51
|
+
Example
|
52
|
+
==================
|
53
|
+
|
54
|
+
name: neatsite
|
55
|
+
version: 5.0
|
56
|
+
script: "rake build"
|
57
|
+
files:
|
58
|
+
- path: build
|
59
|
+
environments:
|
60
|
+
production:
|
61
|
+
files:
|
62
|
+
- path: production-build
|
63
|
+
EOT
|
64
|
+
end
|
65
|
+
optparse.parse!(args)
|
66
|
+
verify_args!(args:args, optparse:optparse, min:0, max:1)
|
67
|
+
options[:options]['name'] = args[0] if args[0]
|
68
|
+
connect(options)
|
69
|
+
payload = {}
|
70
|
+
|
71
|
+
environment = default_deploy_environment
|
72
|
+
if args.count > 0
|
73
|
+
environment = args[0]
|
74
|
+
end
|
75
|
+
if load_deploy_file().nil?
|
76
|
+
raise_command_error "Morpheus Deploy File `morpheus.yml` not detected. Please create one and try again."
|
77
|
+
end
|
78
|
+
|
79
|
+
# Parse and validate config, need instance + deployment + version + files
|
80
|
+
# name can be specified as a single value for both instance and deployment
|
81
|
+
|
82
|
+
deploy_args = merged_deploy_args(environment)
|
83
|
+
|
84
|
+
instance_name = deploy_args['name']
|
85
|
+
if deploy_args['instance'].is_a?(String)
|
86
|
+
instance_name = deploy_args['instance']
|
87
|
+
end
|
88
|
+
if instance_name.nil?
|
89
|
+
raise_command_error "Instance not specified. Please specify the instance name and try again."
|
90
|
+
end
|
91
|
+
|
92
|
+
deployment_name = deploy_args['name'] || instance_name
|
93
|
+
if deploy_args['deployment'].is_a?(String)
|
94
|
+
deployment_name = deploy_args['deployment']
|
95
|
+
end
|
96
|
+
|
97
|
+
version_number = deploy_args['version']
|
98
|
+
if version_number.nil?
|
99
|
+
raise_command_error "Version not specified. Please specify the version and try again."
|
100
|
+
end
|
101
|
+
|
102
|
+
instance_results = @instances_interface.list(name: instance_name)
|
103
|
+
if instance_results['instances'].empty?
|
104
|
+
raise_command_error "Instance not found by name '#{instance_name}'"
|
105
|
+
end
|
106
|
+
instance = instance_results['instances'][0]
|
107
|
+
instance_id = instance['id']
|
108
|
+
|
109
|
+
# ok do it
|
110
|
+
# fetch/create deployment, create deployment version, upload files, and deploy it to instance.
|
111
|
+
|
112
|
+
print_h1 "Morpheus Deployment"
|
113
|
+
|
114
|
+
columns = {
|
115
|
+
"Instance" => :name,
|
116
|
+
"Deployment" => :deployment,
|
117
|
+
"Version" => :version,
|
118
|
+
"Script" => :script,
|
119
|
+
"Post Script" => :post_script,
|
120
|
+
"Files" => :files,
|
121
|
+
"Environment" => :environment,
|
122
|
+
}
|
123
|
+
pretty_file_config = deploy_args['files'].collect {|it|
|
124
|
+
[(it['path'] ? "path: #{it['path']}" : nil), (it['pattern'] ? "pattern: #{it['pattern']}" : nil)].compact.join(", ")
|
125
|
+
}.join(", ")
|
126
|
+
deploy_settings = {
|
127
|
+
:name => instance_name,
|
128
|
+
:deployment => deployment_name,
|
129
|
+
:version => version_number,
|
130
|
+
:script => deploy_args['script'],
|
131
|
+
:post_script => deploy_args['post_script'],
|
132
|
+
:files => pretty_file_config,
|
133
|
+
# :files => deploy_args['files'],
|
134
|
+
# :files => deploy_files.size,
|
135
|
+
# :file_config => (deploy_files.size == 1 ? deploy_files[0][:destination] : deploy_args['files'])
|
136
|
+
:environment => environment
|
137
|
+
}
|
138
|
+
columns.delete("Script") if deploy_settings[:script].nil?
|
139
|
+
columns.delete("Post Script") if deploy_settings[:post_script].nil?
|
140
|
+
columns.delete("Environment") if deploy_settings[:environment].nil?
|
141
|
+
print_description_list(columns, deploy_settings)
|
142
|
+
print reset, "\n"
|
143
|
+
|
144
|
+
if !deploy_args['script'].nil?
|
145
|
+
# do this for dry run too since this is usually what creates the files to be uploaded
|
146
|
+
print cyan, "Executing Pre Deploy Script...", reset, "\n"
|
147
|
+
puts "running command: #{deploy_args['script']}"
|
148
|
+
if !system(deploy_args['script'])
|
149
|
+
raise_command_error "Error executing pre script..."
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Find Files to Upload
|
154
|
+
deploy_files = []
|
155
|
+
if deploy_args['files'].nil? || deploy_args['files'].empty? || !deploy_args['files'].is_a?(Array)
|
156
|
+
raise_command_error "Files not specified. Please specify files array, each item may specify a path or pattern of file(s) to upload"
|
157
|
+
else
|
158
|
+
#print "\n",cyan, "Finding Files...", reset, "\n"
|
159
|
+
current_working_dir = Dir.pwd
|
160
|
+
deploy_args['files'].each do |fmap|
|
161
|
+
Dir.chdir(fmap['path'] || current_working_dir)
|
162
|
+
files = Dir.glob(fmap['pattern'] || '**/*')
|
163
|
+
files.each do |file|
|
164
|
+
if File.file?(file)
|
165
|
+
destination = file.split("/")[0..-2].join("/")
|
166
|
+
# deploy_files << {filepath: File.expand_path(file), destination: destination}
|
167
|
+
deploy_files << {filepath: File.expand_path(file), destination: file}
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
#print cyan, "Found #{deploy_files.size} Files to Upload!", reset, "\n"
|
172
|
+
Dir.chdir(current_working_dir)
|
173
|
+
end
|
174
|
+
|
175
|
+
if deploy_files.empty?
|
176
|
+
raise_command_error "0 files found for: #{deploy_args['files'].inspect}"
|
177
|
+
else
|
178
|
+
print cyan, "Found #{deploy_files.size} Files to Upload!", reset, "\n"
|
179
|
+
end
|
180
|
+
|
181
|
+
unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to create deployment version #{version_number} (#{deploy_files.size} #{deploy_files.size == 1 ? 'file' : 'files'}) and deploy it to instance #{instance['name']}?")
|
182
|
+
return 9, "aborted command"
|
183
|
+
end
|
184
|
+
|
185
|
+
# Find or Create Deployment
|
186
|
+
deployment = nil
|
187
|
+
deployments = @deployments_interface.list(name: deployment_name)['deployments']
|
188
|
+
|
189
|
+
@instances_interface.setopts(options)
|
190
|
+
@deploy_interface.setopts(options)
|
191
|
+
@deployments_interface.setopts(options)
|
192
|
+
|
193
|
+
if deployments.size > 1
|
194
|
+
raise_command_error "#{deployments.size} deployment versions found by deployment '#{name}'"
|
195
|
+
elsif deployments.size == 1
|
196
|
+
deployment = deployments[0]
|
197
|
+
# should update here, eg description
|
198
|
+
else
|
199
|
+
# create it
|
200
|
+
payload = {
|
201
|
+
'deployment' => {
|
202
|
+
'name' => deployment_name
|
203
|
+
}
|
204
|
+
}
|
205
|
+
payload['deployment']['description'] = deploy_args['description'] if deploy_args['description']
|
206
|
+
|
207
|
+
if options[:dry_run]
|
208
|
+
print_dry_run @deployments_interface.dry.create(payload)
|
209
|
+
# return 0, nil
|
210
|
+
deployment = {'id' => ':deploymentId', 'name' => deployment_name}
|
211
|
+
else
|
212
|
+
json_response = @deployments_interface.create(payload)
|
213
|
+
deployment = json_response['deployment']
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Find or Create Deployment Version
|
218
|
+
# Actually, for now this this errors if the version already exists, but it should update it.
|
219
|
+
|
220
|
+
@deployments_interface = @api_client.deployments
|
221
|
+
deployment_version = nil
|
222
|
+
if options[:dry_run]
|
223
|
+
print_dry_run @deployments_interface.dry.list_versions(deployment['id'], {userVersion: version_number})
|
224
|
+
# return 0, nil
|
225
|
+
#deployment_versions =[{'id' => ':versionId', 'version' => version_number}]
|
226
|
+
deployment_versions = []
|
227
|
+
else
|
228
|
+
deployment_versions = @deployments_interface.list_versions(deployment['id'], {userVersion: version_number})['versions']
|
229
|
+
@deployments_interface.setopts(options)
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
if deployment_versions.size > 0
|
234
|
+
raise_command_error "Deployment '#{deployment['name']}' version '#{version_number}' already exists. Specify a new version or delete the existing version."
|
235
|
+
# if deployment_versions.size > 1
|
236
|
+
# raise_command_error "#{deployment_versions.size} versions found by version '#{name}'"
|
237
|
+
# elsif deployment_versions.size == 1
|
238
|
+
# deployment_version = deployment_versions[0]
|
239
|
+
# # should update here, eg description
|
240
|
+
else
|
241
|
+
# create it
|
242
|
+
payload = {
|
243
|
+
'version' => {
|
244
|
+
'userVersion' => version_number,
|
245
|
+
'deployType' => (deploy_args['type'] || deploy_args['deployType'] || 'file')
|
246
|
+
}
|
247
|
+
}
|
248
|
+
payload['version']['fetchUrl'] = deploy_args['fetchUrl'] if deploy_args['fetchUrl']
|
249
|
+
payload['version']['gitUrl'] = deploy_args['gitUrl'] if deploy_args['gitUrl']
|
250
|
+
payload['version']['gitRef'] = deploy_args['gitRef'] if deploy_args['gitRef']
|
251
|
+
|
252
|
+
if options[:dry_run]
|
253
|
+
print_dry_run @deployments_interface.dry.create_version(deployment['id'], payload)
|
254
|
+
# return 0, nil
|
255
|
+
deployment_version = {'id' => ':versionId', 'version' => version_number}
|
256
|
+
else
|
257
|
+
json_response = @deployments_interface.create_version(deployment['id'], payload)
|
258
|
+
deployment_version = json_response['version']
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
# Upload Files
|
264
|
+
if deploy_files && !deploy_files.empty?
|
265
|
+
print "\n",cyan, "Uploading #{deploy_files.size} Files...", reset, "\n"
|
266
|
+
current_working_dir = Dir.pwd
|
267
|
+
deploy_files.each do |f|
|
268
|
+
destination = f[:destination]
|
269
|
+
if options[:dry_run]
|
270
|
+
print_dry_run @deployments_interface.upload_file(deployment['id'], deployment_version['id'], f[:filepath], f[:destination])
|
271
|
+
else
|
272
|
+
print cyan," - Uploading #{f[:destination]} ...", reset if !options[:quiet]
|
273
|
+
upload_result = @deployments_interface.upload_file(deployment['id'], deployment_version['id'], f[:filepath], f[:destination])
|
274
|
+
#print green + "SUCCESS" + reset + "\n" if !options[:quiet]
|
275
|
+
print reset, "\n" if !options[:quiet]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
print cyan, "Upload Complete!", reset, "\n"
|
279
|
+
Dir.chdir(current_working_dir)
|
280
|
+
else
|
281
|
+
print "\n",cyan, "0 files to upload", reset, "\n"
|
282
|
+
end
|
283
|
+
|
284
|
+
# TODO: support deploying other deployTypes too, git and fetch
|
285
|
+
|
286
|
+
if !deploy_args['post_script'].nil?
|
287
|
+
print cyan, "Executing Post Script...", reset, "\n"
|
288
|
+
puts "running command: #{deploy_args['post_script']}"
|
289
|
+
if !system(deploy_args['post_script'])
|
290
|
+
raise_command_error "Error executing post script..."
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# JD: restart for evars eh?
|
295
|
+
if deploy_args['env']
|
296
|
+
evars = []
|
297
|
+
deploy_args['env'].each_pair do |key, value|
|
298
|
+
evars << {name: key, value: value, export: false}
|
299
|
+
end
|
300
|
+
payload = {envs: evars}
|
301
|
+
if options[:dry_run]
|
302
|
+
print_dry_run @instances_interface.dry.create_env(instance_id, payload)
|
303
|
+
print_dry_run @instances_interface.dry.restart(instance_id)
|
304
|
+
else
|
305
|
+
@instances_interface.create_env(instance_id, payload)
|
306
|
+
@instances_interface.restart(instance_id)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
# Create the AppDeploy, this does the deploy async (as of 4.2.2-3)
|
310
|
+
payload = {'appDeploy' => {} }
|
311
|
+
payload['appDeploy']['versionId'] = deployment_version['id']
|
312
|
+
if deploy_args['options']
|
313
|
+
payload['appDeploy']['config'] = deploy_args['options']
|
314
|
+
end
|
315
|
+
# stageOnly means do not actually deploy yet, can invoke @deploy_interface.deploy(deployment['id']) later
|
316
|
+
# there is no cli command for that yet though..
|
317
|
+
stage_only = deploy_args['stage_deploy'] || deploy_args['stage_only'] || deploy_args['stageOnly']
|
318
|
+
if stage_only
|
319
|
+
payload['appDeploy']['stageOnly'] = true
|
320
|
+
end
|
321
|
+
app_deploy_id = nil
|
322
|
+
if options[:dry_run]
|
323
|
+
print_dry_run @deploy_interface.dry.create(instance_id, payload)
|
324
|
+
# return 0, nil
|
325
|
+
app_deploy_id = ':appDeployId'
|
326
|
+
else
|
327
|
+
# Create a new appDeploy record, without stageOnly, this actually does the deployment
|
328
|
+
print cyan, "Deploying #{deployment_name} version #{version_number} to instance #{instance_name} ...", reset, "\n"
|
329
|
+
deploy_result = @deploy_interface.create(instance_id, payload)
|
330
|
+
app_deploy = deploy_result['appDeploy']
|
331
|
+
app_deploy_id = app_deploy['id']
|
332
|
+
print_green_success "Deploy Successful!"
|
333
|
+
end
|
334
|
+
return 0, nil
|
335
|
+
end
|
336
|
+
|
337
|
+
protected
|
338
|
+
|
339
|
+
# Loads a morpheus.yml file from within the current working directory.
|
340
|
+
# This file contains information necessary to perform a deployment via the cli.
|
341
|
+
#
|
342
|
+
# === Example File Attributes
|
343
|
+
# * +script+ - The initial script to run before uploading files
|
344
|
+
# * +name+ - The instance name we are deploying to (can be overridden in CLI)
|
345
|
+
# * +files+ - List of file patterns to use for uploading files and their target destination
|
346
|
+
# * +options+ - Map of deployment options depending on deployment type
|
347
|
+
# * +post_script+ - A post operation script to be run on the local machine
|
348
|
+
# * +stage_deploy+ - If set to true the deploy will only be staged and not actually run
|
349
|
+
#
|
350
|
+
# +NOTE: + It is also possible to nest these properties in an "environments" map to override based on a passed environment deploy name
|
351
|
+
#
|
352
|
+
def load_deploy_file
|
353
|
+
if !File.exist? "morpheus.yml"
|
354
|
+
puts "No morpheus.yml file detected in the current directory. Nothing to do."
|
355
|
+
return nil
|
356
|
+
end
|
357
|
+
|
358
|
+
@deploy_file = YAML.load_file("morpheus.yml")
|
359
|
+
return @deploy_file
|
360
|
+
end
|
361
|
+
|
362
|
+
def merged_deploy_args(environment)
|
363
|
+
deploy_args = @deploy_file.reject { |key,value| key == 'environment'}
|
364
|
+
if environment && !@deploy_file['environment'].nil? && !@deploy_file['environment'][environment].nil?
|
365
|
+
deploy_args = deploy_args.merge(@deploy_file['environment'][environment])
|
366
|
+
end
|
367
|
+
return deploy_args
|
368
|
+
end
|
369
|
+
|
370
|
+
def default_deploy_environment
|
371
|
+
nil
|
372
|
+
end
|
373
|
+
|
374
|
+
end
|
@@ -1,12 +1,12 @@
|
|
1
|
-
require 'io/console'
|
2
|
-
require 'rest_client'
|
3
|
-
require 'optparse'
|
4
1
|
require 'morpheus/cli/cli_command'
|
5
2
|
|
6
3
|
class Morpheus::Cli::Deployments
|
7
4
|
include Morpheus::Cli::CliCommand
|
5
|
+
include Morpheus::Cli::DeploymentsHelper
|
8
6
|
|
9
|
-
register_subcommands :list, :add, :update, :remove
|
7
|
+
register_subcommands :list, :get, :add, :update, :remove
|
8
|
+
register_subcommands :list_versions, :get_version, :add_version, :update_version, :remove_version
|
9
|
+
alias_subcommand :versions, :'list-versions'
|
10
10
|
|
11
11
|
def initialize()
|
12
12
|
# @appliance_name, @appliance_url = Morpheus::Cli::Remote.active_appliance
|
@@ -14,7 +14,7 @@ class Morpheus::Cli::Deployments
|
|
14
14
|
|
15
15
|
def connect(opts)
|
16
16
|
@api_client = establish_remote_appliance_connection(opts)
|
17
|
-
@deployments_interface =
|
17
|
+
@deployments_interface = @api_client.deployments
|
18
18
|
end
|
19
19
|
|
20
20
|
def handle(args)
|
@@ -23,264 +23,588 @@ class Morpheus::Cli::Deployments
|
|
23
23
|
|
24
24
|
def list(args)
|
25
25
|
options = {}
|
26
|
+
params = {}
|
27
|
+
ref_ids = []
|
26
28
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
27
|
-
opts.banner = subcommand_usage()
|
28
|
-
|
29
|
+
opts.banner = subcommand_usage("[search]")
|
30
|
+
build_standard_list_options(opts, options)
|
31
|
+
opts.footer = "List deployments."
|
29
32
|
end
|
30
33
|
optparse.parse!(args)
|
31
34
|
connect(options)
|
32
|
-
|
33
|
-
|
34
|
-
[:phrase
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
# verify_args!(args:args, optparse:optparse, count:0)
|
36
|
+
if args.count > 0
|
37
|
+
options[:phrase] = args.join(" ")
|
38
|
+
end
|
39
|
+
params.merge!(parse_list_options(options))
|
40
|
+
@deployments_interface.setopts(options)
|
41
|
+
if options[:dry_run]
|
42
|
+
print_dry_run @deployments_interface.dry.list(params)
|
43
|
+
return
|
44
|
+
end
|
45
|
+
json_response = @deployments_interface.list(params)
|
46
|
+
deployments = json_response['deployments']
|
47
|
+
render_response(json_response, options, 'deployments') do
|
48
|
+
print_h1 "Morpheus Deployments", parse_list_subtitles(options), options
|
49
|
+
if deployments.empty?
|
50
|
+
print cyan,"No deployments found.",reset,"\n"
|
51
|
+
else
|
52
|
+
print as_pretty_table(deployments, deployment_column_definitions.upcase_keys!, options)
|
53
|
+
print_results_pagination(json_response)
|
41
54
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
55
|
+
print reset,"\n"
|
56
|
+
end
|
57
|
+
if deployments.empty?
|
58
|
+
return 1, "no deployments found"
|
59
|
+
else
|
60
|
+
return 0, nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def get(args)
|
65
|
+
params = {}
|
66
|
+
options = {}
|
67
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
68
|
+
opts.banner = subcommand_usage("[deployment]")
|
69
|
+
build_standard_get_options(opts, options)
|
70
|
+
opts.footer = <<-EOT
|
71
|
+
Get details about a specific deployment.
|
72
|
+
[deployment] is required. This is the name or id of a deployment.
|
73
|
+
EOT
|
74
|
+
end
|
75
|
+
optparse.parse!(args)
|
76
|
+
verify_args!(args:args, optparse:optparse, min:1)
|
77
|
+
connect(options)
|
78
|
+
id_list = parse_id_list(args)
|
79
|
+
# lookup IDs if names are given
|
80
|
+
id_list = id_list.collect do |id|
|
81
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
82
|
+
id
|
45
83
|
else
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
print cyan,"No deployments found.",reset,"\n"
|
84
|
+
deployment = find_deployment_by_name(id)
|
85
|
+
if deployment
|
86
|
+
deployment['id']
|
50
87
|
else
|
51
|
-
|
52
|
-
rows = deployments.collect do |deployment|
|
53
|
-
{name: deployment['name'], id: deployment['id'], description: deployment['description'], updated: format_local_dt(deployment['lastUpdated'])}
|
54
|
-
end
|
55
|
-
columns = [:id, :name, :description, :updated]
|
56
|
-
print as_pretty_table(rows, columns, options)
|
88
|
+
raise_command_error "deployment not found for name '#{id}'"
|
57
89
|
end
|
58
|
-
print reset,"\n"
|
59
90
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
91
|
+
end
|
92
|
+
return run_command_for_each_arg(id_list) do |arg|
|
93
|
+
_get(arg, params, options)
|
63
94
|
end
|
64
95
|
end
|
65
96
|
|
97
|
+
def _get(id, params, options)
|
98
|
+
@deployments_interface.setopts(options)
|
99
|
+
if options[:dry_run]
|
100
|
+
print_dry_run @deployments_interface.dry.get(id, params)
|
101
|
+
print_dry_run @deployments_interface.dry.list_versions(id, {})
|
102
|
+
return
|
103
|
+
end
|
104
|
+
json_response = @deployments_interface.get(id, params)
|
105
|
+
deployment_versions = @deployments_interface.list_versions(id)['versions']
|
106
|
+
deployment = json_response['deployment']
|
107
|
+
render_response(json_response, options, 'deployment') do
|
108
|
+
print_h1 "Deployment Details", [], options
|
109
|
+
print cyan
|
110
|
+
print_description_list(deployment_column_definitions, deployment)
|
111
|
+
print_h2 "Versions", options
|
112
|
+
if deployment_versions.empty?
|
113
|
+
print cyan,"No versions found.",reset,"\n"
|
114
|
+
else
|
115
|
+
print as_pretty_table(deployment_versions, deployment_version_column_definitions.upcase_keys!, options)
|
116
|
+
print_results_pagination({'size' => deployment_versions.size(), 'total' => deployment['versionCount']}, {:label => "version", :n_label => "versions"})
|
117
|
+
end
|
118
|
+
print reset,"\n"
|
119
|
+
end
|
120
|
+
return 0, nil
|
121
|
+
end
|
122
|
+
|
66
123
|
def list_versions(args)
|
124
|
+
params = {}
|
67
125
|
options = {}
|
68
126
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
69
|
-
opts.banner = subcommand_usage("[
|
70
|
-
|
127
|
+
opts.banner = subcommand_usage("[deployment] [search]")
|
128
|
+
build_standard_list_options(opts, options)
|
129
|
+
opts.footer = <<-EOT
|
130
|
+
List versions of a specific deployment.
|
131
|
+
[deployment] is required. This is the name or id of a deployment.
|
132
|
+
EOT
|
71
133
|
end
|
72
134
|
optparse.parse!(args)
|
73
|
-
|
74
|
-
puts optparse
|
75
|
-
exit 1
|
76
|
-
end
|
135
|
+
verify_args!(args:args, optparse:optparse, min:1,max:2)
|
77
136
|
deployment_name = args[0]
|
137
|
+
if args.count > 1
|
138
|
+
options[:phrase] = args[1]
|
139
|
+
end
|
78
140
|
connect(options)
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
puts JSON.pretty_generate(json_response)
|
141
|
+
params.merge!(parse_list_options(options))
|
142
|
+
@deployments_interface.setopts(options)
|
143
|
+
if options[:dry_run]
|
144
|
+
print_dry_run @deployments_interface.dry.list(params)
|
145
|
+
return
|
146
|
+
end
|
147
|
+
deployment = find_deployment_by_name_or_id(deployment_name)
|
148
|
+
exit 1 if deployment.nil?
|
149
|
+
json_response = @deployments_interface.list_versions(deployment['id'], params)
|
150
|
+
deployment_versions = json_response['versions']
|
151
|
+
render_response(json_response, options, 'versions') do
|
152
|
+
print_h1 "Deployment Versions", ["#{deployment['name']}"] + parse_list_subtitles(options), options
|
153
|
+
if deployment_versions.empty?
|
154
|
+
print cyan,"No versions found.",reset,"\n"
|
94
155
|
else
|
95
|
-
|
96
|
-
|
97
|
-
if versions.empty?
|
98
|
-
print cyan,"No deployment versions found.",reset,"\n"
|
99
|
-
else
|
100
|
-
print cyan
|
101
|
-
rows = versions.collect do |version|
|
102
|
-
{version: version['userVersion'], type: version['deployType'], updated: format_local_dt(version['lastUpdated'])}
|
103
|
-
end
|
104
|
-
columns = [:version, :type, :updated]
|
105
|
-
print as_pretty_table(rows, columns, options)
|
106
|
-
end
|
107
|
-
print reset,"\n"
|
156
|
+
print as_pretty_table(deployment_versions, deployment_version_column_definitions.upcase_keys!, options)
|
157
|
+
print_results_pagination(json_response)
|
108
158
|
end
|
109
|
-
|
110
|
-
|
111
|
-
|
159
|
+
print reset,"\n"
|
160
|
+
end
|
161
|
+
if deployment_versions.empty?
|
162
|
+
return 1, "no versions found"
|
163
|
+
else
|
164
|
+
return 0, nil
|
112
165
|
end
|
113
166
|
end
|
114
167
|
|
115
|
-
def
|
116
|
-
deployment_name = args[0]
|
168
|
+
def add(args)
|
117
169
|
options = {}
|
118
|
-
|
170
|
+
params = {}
|
119
171
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
120
172
|
opts.banner = subcommand_usage("[name] [options]")
|
121
|
-
|
173
|
+
build_option_type_options(opts, options, add_deployment_option_types)
|
174
|
+
build_option_type_options(opts, options, add_deployment_advanced_option_types)
|
175
|
+
build_standard_add_options(opts, options)
|
176
|
+
opts.footer = <<-EOT
|
177
|
+
Create a new deployment.
|
178
|
+
EOT
|
122
179
|
end
|
123
180
|
optparse.parse!(args)
|
124
|
-
|
125
|
-
|
126
|
-
exit 1
|
127
|
-
end
|
181
|
+
verify_args!(args:args, optparse:optparse, min:0, max:1)
|
182
|
+
options[:options]['name'] = args[0] if args[0]
|
128
183
|
connect(options)
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
184
|
+
payload = {}
|
185
|
+
if options[:payload]
|
186
|
+
payload = options[:payload]
|
187
|
+
payload.deep_merge!({'deployment' => parse_passed_options(options)})
|
188
|
+
else
|
189
|
+
payload.deep_merge!({'deployment' => parse_passed_options(options)})
|
190
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(add_deployment_option_types, options[:options], @api_client, options[:params])
|
191
|
+
params.deep_merge!(v_prompt)
|
192
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_deployment_advanced_option_types, options[:options], @api_client, options[:params])
|
193
|
+
advanced_config.deep_compact!
|
194
|
+
params.deep_merge!(advanced_config)
|
195
|
+
payload['deployment'].deep_merge!(params)
|
196
|
+
end
|
197
|
+
@deployments_interface.setopts(options)
|
198
|
+
if options[:dry_run]
|
199
|
+
print_dry_run @deployments_interface.dry.create(payload)
|
200
|
+
return 0, nil
|
201
|
+
end
|
202
|
+
json_response = @deployments_interface.create(payload)
|
203
|
+
deployment = json_response['deployment']
|
204
|
+
render_response(json_response, options, 'deployment') do
|
205
|
+
print_green_success "Added deployment #{deployment['name']}"
|
206
|
+
return _get(deployment["id"], {}, options)
|
207
|
+
end
|
208
|
+
return 0, nil
|
209
|
+
end
|
135
210
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
211
|
+
def update(args)
|
212
|
+
options = {}
|
213
|
+
params = {}
|
214
|
+
payload = {}
|
215
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
216
|
+
opts.banner = subcommand_usage("[deployment] [options]")
|
217
|
+
build_option_type_options(opts, options, update_deployment_option_types)
|
218
|
+
build_option_type_options(opts, options, update_deployment_advanced_option_types)
|
219
|
+
build_standard_update_options(opts, options)
|
220
|
+
opts.footer = <<-EOT
|
221
|
+
Update a deployment.
|
222
|
+
[deployment] is required. This is the name or id of a deployment.
|
223
|
+
EOT
|
224
|
+
end
|
225
|
+
optparse.parse!(args)
|
226
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
227
|
+
connect(options)
|
228
|
+
deployment = find_deployment_by_name_or_id(args[0])
|
229
|
+
return 1 if deployment.nil?
|
230
|
+
payload = {}
|
231
|
+
if options[:payload]
|
232
|
+
payload = options[:payload]
|
233
|
+
payload.deep_merge!({'deployment' => parse_passed_options(options)})
|
234
|
+
else
|
235
|
+
payload.deep_merge!({'deployment' => parse_passed_options(options)})
|
236
|
+
# do not prompt on update
|
237
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_deployment_option_types, options[:options], @api_client, options[:params])
|
238
|
+
v_prompt.deep_compact!
|
239
|
+
params.deep_merge!(v_prompt)
|
240
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_deployment_advanced_option_types, options[:options], @api_client, options[:params])
|
241
|
+
advanced_config.deep_compact!
|
242
|
+
params.deep_merge!(advanced_config)
|
243
|
+
payload.deep_merge!({'deployment' => params})
|
244
|
+
if payload['deployment'].empty? # || options[:no_prompt]
|
245
|
+
raise_command_error "Specify at least one option to update.\n#{optparse}"
|
141
246
|
end
|
247
|
+
end
|
248
|
+
@deployments_interface.setopts(options)
|
249
|
+
if options[:dry_run]
|
250
|
+
print_dry_run @deployments_interface.dry.update(deployment['id'], payload)
|
251
|
+
return
|
252
|
+
end
|
253
|
+
json_response = @deployments_interface.update(deployment['id'], payload)
|
254
|
+
deployment = json_response['deployment']
|
255
|
+
render_response(json_response, options, 'deployment') do
|
256
|
+
print_green_success "Updated deployment #{deployment['name']}"
|
257
|
+
return _get(deployment["id"], {}, options)
|
258
|
+
end
|
259
|
+
return 0, nil
|
260
|
+
end
|
142
261
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
262
|
+
def remove(args)
|
263
|
+
options = {}
|
264
|
+
params = {}
|
265
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
266
|
+
opts.banner = subcommand_usage("[deployment] [options]")
|
267
|
+
build_standard_remove_options(opts, options)
|
268
|
+
opts.footer = <<-EOT
|
269
|
+
Delete a deployment.
|
270
|
+
[deployment] is required. This is the name or id of a deployment.
|
271
|
+
EOT
|
272
|
+
end
|
273
|
+
optparse.parse!(args)
|
274
|
+
verify_args!(args:args, optparse:optparse, count:1)
|
275
|
+
connect(options)
|
276
|
+
deployment = find_deployment_by_name_or_id(args[0])
|
277
|
+
return 1 if deployment.nil?
|
278
|
+
@deployments_interface.setopts(options)
|
279
|
+
if options[:dry_run]
|
280
|
+
print_dry_run @deployments_interface.dry.destroy(deployment['id'], params)
|
281
|
+
return
|
282
|
+
end
|
283
|
+
json_response = @deployments_interface.destroy(deployment['id'], params)
|
284
|
+
render_response(json_response, options) do
|
285
|
+
print_green_success "Removed deployment #{deployment['name']}"
|
286
|
+
end
|
287
|
+
return 0, nil
|
288
|
+
end
|
150
289
|
|
290
|
+
def get_version(args)
|
291
|
+
options = {}
|
292
|
+
params = {}
|
293
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
294
|
+
opts.banner = subcommand_usage("[deployment] [version] [options]")
|
295
|
+
build_option_type_options(opts, options, add_deployment_version_option_types)
|
296
|
+
build_option_type_options(opts, options, add_deployment_version_advanced_option_types)
|
297
|
+
build_standard_add_options(opts, options)
|
298
|
+
opts.footer = <<-EOT
|
299
|
+
Create a new deployment version.
|
300
|
+
[deployment] is required. This is the name or id of a deployment.
|
301
|
+
[version] is required. This is the deployment version identifier
|
302
|
+
EOT
|
303
|
+
end
|
304
|
+
optparse.parse!(args)
|
305
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
306
|
+
connect(options)
|
151
307
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
308
|
+
deployment = find_deployment_by_name_or_id(args[0])
|
309
|
+
return 1 if deployment.nil?
|
310
|
+
id = args[1]
|
311
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
312
|
+
id = id.to_i
|
313
|
+
else
|
314
|
+
deployment_version = find_deployment_version_by_name(deployment['id'], id)
|
315
|
+
if deployment_version
|
316
|
+
id = deployment_version['id']
|
317
|
+
else
|
318
|
+
# raise_command_error "deployment not found for name '#{id}'"
|
319
|
+
return 1, "deployment version not found for name '#{id}'"
|
157
320
|
end
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
321
|
+
end
|
322
|
+
@deployments_interface.setopts(options)
|
323
|
+
if options[:dry_run]
|
324
|
+
print_dry_run @deployments_interface.dry.get_version(deployment['id'], id, params)
|
325
|
+
return
|
326
|
+
end
|
327
|
+
json_response = @deployments_interface.get_version(deployment['id'], id, params)
|
328
|
+
deployment_version = json_response['version']
|
329
|
+
render_response(json_response, options, 'version') do
|
330
|
+
# print_h1 "Deployment Version Details", [deployment['name']], options
|
331
|
+
print_h1 "Deployment Version Details", [], options
|
332
|
+
print cyan
|
333
|
+
#columns = deployment_version_column_definitions
|
334
|
+
columns = {
|
335
|
+
"ID" => 'id',
|
336
|
+
"Deployment" => lambda {|it| deployment['name'] },
|
337
|
+
"Version" => 'userVersion',
|
338
|
+
"Deploy Type" => lambda {|it| it['deployType'] },
|
339
|
+
"URL" => lambda {|it|
|
340
|
+
if it['deployType'] == 'fetch'
|
341
|
+
"#{it['fetchUrl']}"
|
342
|
+
elsif it['deployType'] == 'git'
|
343
|
+
"#{it['gitUrl']}"
|
344
|
+
end
|
345
|
+
},
|
346
|
+
"Ref" => lambda {|it|
|
347
|
+
if it['deployType'] == 'git'
|
348
|
+
"#{it['gitRef']}"
|
349
|
+
end
|
350
|
+
},
|
351
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
352
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
353
|
+
}
|
354
|
+
if deployment_version['deployType'] == 'git'
|
355
|
+
columns['Git URL'] = columns['URL']
|
356
|
+
elsif deployment_version['deployType'] == 'fetch'
|
357
|
+
columns['Fetch URL'] = columns['URL']
|
358
|
+
columns.delete('Ref')
|
164
359
|
else
|
165
|
-
|
360
|
+
columns.delete('URL')
|
361
|
+
columns.delete('Ref')
|
166
362
|
end
|
167
|
-
|
168
|
-
|
169
|
-
exit 1
|
363
|
+
print_description_list(columns, deployment_version)
|
364
|
+
print reset,"\n"
|
170
365
|
end
|
366
|
+
return 0, nil
|
171
367
|
end
|
172
368
|
|
173
|
-
def
|
369
|
+
def add_version(args)
|
174
370
|
options = {}
|
371
|
+
params = {}
|
175
372
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
176
|
-
opts.banner = subcommand_usage("[
|
177
|
-
opts
|
178
|
-
|
179
|
-
|
180
|
-
|
373
|
+
opts.banner = subcommand_usage("[deployment] [version] [options]")
|
374
|
+
build_option_type_options(opts, options, add_deployment_version_option_types)
|
375
|
+
build_option_type_options(opts, options, add_deployment_version_advanced_option_types)
|
376
|
+
build_standard_add_options(opts, options)
|
377
|
+
opts.footer = <<-EOT
|
378
|
+
Create a new deployment version.
|
379
|
+
[deployment] is required. This is the name or id of a deployment.
|
380
|
+
[version] is required. This is the deployment version identifier
|
381
|
+
EOT
|
181
382
|
end
|
182
383
|
optparse.parse!(args)
|
183
|
-
|
184
|
-
puts optparse
|
185
|
-
exit 1
|
186
|
-
end
|
187
|
-
deployment_name = args[0]
|
384
|
+
verify_args!(args:args, optparse:optparse, min:0, max:2)
|
188
385
|
connect(options)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
if
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
386
|
+
deployment = nil
|
387
|
+
if args[0]
|
388
|
+
deployment = find_deployment_by_name_or_id(args[0])
|
389
|
+
return 1 if deployment.nil?
|
390
|
+
else
|
391
|
+
deployment_id = Morpheus::Cli::OptionTypes.prompt([{'fieldName' => 'deploymentId', 'fieldLabel' => 'Deployment', 'type' => 'select', 'required' => true, 'description' => 'Deployment to add version to', 'optionSource' => lambda { |api_client, api_params|
|
392
|
+
@deployments_interface.list(max:10000)['deployments'].collect {|it|
|
393
|
+
{'name' => it['name'], 'value' => it['id']}
|
394
|
+
}
|
395
|
+
}}], options[:options])['deploymentId']
|
396
|
+
deployment = {'id' => deployment_id.to_i}
|
397
|
+
end
|
398
|
+
options[:options]['userVersion'] = args[1] if args[1]
|
399
|
+
payload = {}
|
400
|
+
if options[:payload]
|
401
|
+
payload = options[:payload]
|
402
|
+
payload.deep_merge!({'version' => parse_passed_options(options)})
|
403
|
+
else
|
404
|
+
payload.deep_merge!({'version' => parse_passed_options(options)})
|
405
|
+
v_prompt = Morpheus::Cli::OptionTypes.prompt(add_deployment_version_option_types, options[:options], @api_client, options[:params])
|
406
|
+
params.deep_merge!(v_prompt)
|
407
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(add_deployment_version_advanced_option_types, options[:options], @api_client, options[:params])
|
408
|
+
advanced_config.deep_compact!
|
409
|
+
params.deep_merge!(advanced_config)
|
410
|
+
payload['version'].deep_merge!(params)
|
411
|
+
end
|
412
|
+
@deployments_interface.setopts(options)
|
413
|
+
if options[:dry_run]
|
414
|
+
print_dry_run @deployments_interface.dry.create_version(deployment['id'], payload)
|
415
|
+
return 0, nil
|
416
|
+
end
|
417
|
+
json_response = @deployments_interface.create_version(deployment['id'], payload)
|
418
|
+
deployment_version = json_response['version']
|
419
|
+
render_response(json_response, options, 'version') do
|
420
|
+
print_green_success "Added deployment version #{deployment_version['userVersion']}"
|
421
|
+
return get_version([deployment["id"], deployment_version['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
|
205
422
|
end
|
206
423
|
end
|
207
424
|
|
208
|
-
def
|
425
|
+
def update_version(args)
|
209
426
|
options = {}
|
427
|
+
params = {}
|
210
428
|
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
211
|
-
opts.banner = subcommand_usage("[
|
212
|
-
|
429
|
+
opts.banner = subcommand_usage("[deployment] [version] [options]")
|
430
|
+
build_option_type_options(opts, options, update_deployment_version_option_types)
|
431
|
+
build_option_type_options(opts, options, update_deployment_version_advanced_option_types)
|
432
|
+
build_standard_update_options(opts, options)
|
433
|
+
opts.footer = <<-EOT
|
434
|
+
Update a deployment version.
|
435
|
+
[deployment] is required. This is the name or id of a deployment.
|
436
|
+
[version] is required. This is the deployment version identifier
|
437
|
+
EOT
|
213
438
|
end
|
214
439
|
optparse.parse!(args)
|
215
|
-
|
216
|
-
|
217
|
-
|
440
|
+
verify_args!(args:args, optparse:optparse, min:0, max:2)
|
441
|
+
connect(options)
|
442
|
+
deployment = find_deployment_by_name_or_id(args[0])
|
443
|
+
return 1 if deployment.nil?
|
444
|
+
deployment_version = find_deployment_version_by_name_or_id(deployment['id'], args[1])
|
445
|
+
return 1 if deployment_version.nil?
|
446
|
+
payload = {}
|
447
|
+
if options[:payload]
|
448
|
+
payload = options[:payload]
|
449
|
+
payload.deep_merge!({'version' => parse_passed_options(options)})
|
450
|
+
else
|
451
|
+
payload.deep_merge!({'version' => parse_passed_options(options)})
|
452
|
+
v_prompt = Morpheus::Cli::OptionTypes.no_prompt(update_deployment_version_option_types, options[:options], @api_client, options[:params])
|
453
|
+
params.deep_merge!(v_prompt)
|
454
|
+
advanced_config = Morpheus::Cli::OptionTypes.no_prompt(update_deployment_version_advanced_option_types, options[:options], @api_client, options[:params])
|
455
|
+
advanced_config.deep_compact!
|
456
|
+
params.deep_merge!(advanced_config)
|
457
|
+
payload['version'].deep_merge!(params)
|
458
|
+
end
|
459
|
+
@deployments_interface.setopts(options)
|
460
|
+
if options[:dry_run]
|
461
|
+
print_dry_run @deployments_interface.dry.update_version(deployment['id'], deployment_version['id'], payload)
|
462
|
+
return 0, nil
|
463
|
+
end
|
464
|
+
json_response = @deployments_interface.update_version(deployment['id'], deployment_version['id'], payload)
|
465
|
+
deployment_version = json_response['version']
|
466
|
+
render_response(json_response, options, 'version') do
|
467
|
+
print_green_success "Updated deployment version #{deployment_version['userVersion']}"
|
468
|
+
return get_version([deployment["id"], deployment_version['id']] + (options[:remote] ? ["-r",options[:remote]] : []))
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
def remove_version(args)
|
473
|
+
options = {}
|
474
|
+
params = {}
|
475
|
+
optparse = Morpheus::Cli::OptionParser.new do |opts|
|
476
|
+
opts.banner = subcommand_usage("[deployment] [version] [options]")
|
477
|
+
build_standard_remove_options(opts, options)
|
478
|
+
opts.footer = <<-EOT
|
479
|
+
Delete a deployment version.
|
480
|
+
[deployment] is required. This is the name or id of a deployment.
|
481
|
+
[version] is required. This is the version identifier of a deployment version.
|
482
|
+
EOT
|
218
483
|
end
|
219
|
-
|
484
|
+
optparse.parse!(args)
|
485
|
+
verify_args!(args:args, optparse:optparse, count:2)
|
220
486
|
connect(options)
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
end
|
232
|
-
json_response = @deployments_interface.destroy(deployment['id'])
|
233
|
-
if options[:json]
|
234
|
-
print JSON.pretty_generate(json_response)
|
487
|
+
deployment = find_deployment_by_name_or_id(args[0])
|
488
|
+
return 1 if deployment.nil?
|
489
|
+
id = args[1]
|
490
|
+
|
491
|
+
if id.to_s =~ /\A\d{1,}\Z/
|
492
|
+
id = id.to_i
|
493
|
+
else
|
494
|
+
deployment_version = find_deployment_version_by_name(deployment['id'], id)
|
495
|
+
if deployment_version
|
496
|
+
id = deployment_version['id']
|
235
497
|
else
|
236
|
-
|
498
|
+
# raise_command_error "deployment not found for '#{id}'"
|
499
|
+
return 1, "deployment version not found for '#{id}'"
|
237
500
|
end
|
238
|
-
rescue RestClient::Exception => e
|
239
|
-
print_rest_exception(e, options)
|
240
|
-
exit 1
|
241
501
|
end
|
502
|
+
@deployments_interface.setopts(options)
|
503
|
+
if options[:dry_run]
|
504
|
+
print_dry_run @deployments_interface.dry.destroy(deployment['id'], params)
|
505
|
+
return
|
506
|
+
end
|
507
|
+
json_response = @deployments_interface.destroy(deployment['id'], params)
|
508
|
+
render_response(json_response, options) do
|
509
|
+
print_green_success "Removed deployment version #{deployment_version['userVersion']}"
|
510
|
+
end
|
511
|
+
return 0, nil
|
242
512
|
end
|
243
513
|
|
244
|
-
|
245
514
|
private
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
515
|
+
|
516
|
+
def deployment_column_definitions
|
517
|
+
{
|
518
|
+
"ID" => 'id',
|
519
|
+
"Name" => 'name',
|
520
|
+
"Description" => 'description',
|
521
|
+
"Versions" => lambda {|it| it['versionCount'] },
|
522
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
523
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
524
|
+
}
|
525
|
+
end
|
526
|
+
|
527
|
+
# this is not so simple, need to first choose select instance, host or provider
|
528
|
+
def add_deployment_option_types
|
529
|
+
[
|
530
|
+
{'fieldName' => 'name', 'fieldLabel' => 'Name', 'type' => 'text', 'required' => true, 'displayOrder' => 1},
|
531
|
+
{'fieldName' => 'description', 'fieldLabel' => 'Description', 'type' => 'text', 'displayOrder' => 1}
|
532
|
+
]
|
533
|
+
end
|
534
|
+
|
535
|
+
def add_deployment_advanced_option_types
|
536
|
+
[]
|
261
537
|
end
|
262
538
|
|
263
|
-
def
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
elsif val.to_i.to_s == val
|
270
|
-
results = @deployments_interface.deployment_types(val.to_i)
|
271
|
-
result = results['deploymentType']
|
272
|
-
end
|
273
|
-
if result.nil?
|
274
|
-
print_red_alert "Deployment Type not found by '#{val}'"
|
275
|
-
return nil
|
276
|
-
end
|
277
|
-
return result
|
539
|
+
def update_deployment_option_types
|
540
|
+
add_deployment_option_types.collect {|it|
|
541
|
+
it.delete('required')
|
542
|
+
it.delete('defaultValue')
|
543
|
+
it
|
544
|
+
}
|
278
545
|
end
|
279
546
|
|
280
|
-
def
|
547
|
+
def update_deployment_advanced_option_types
|
548
|
+
add_deployment_advanced_option_types.collect {|it|
|
549
|
+
it.delete('required')
|
550
|
+
it.delete('defaultValue')
|
551
|
+
it
|
552
|
+
}
|
553
|
+
end
|
554
|
+
|
555
|
+
## Deployment Versions
|
556
|
+
|
557
|
+
def deployment_version_column_definitions
|
558
|
+
{
|
559
|
+
"ID" => 'id',
|
560
|
+
"Version" => 'userVersion',
|
561
|
+
"Deploy Type" => lambda {|it| it['deployType'] },
|
562
|
+
"URL" => lambda {|it|
|
563
|
+
if it['deployType'] == 'fetch'
|
564
|
+
"#{it['fetchUrl']}"
|
565
|
+
elsif it['deployType'] == 'git'
|
566
|
+
"#{it['gitUrl']}"
|
567
|
+
end
|
568
|
+
},
|
569
|
+
"Ref" => lambda {|it|
|
570
|
+
if it['deployType'] == 'git'
|
571
|
+
"#{it['gitRef']}"
|
572
|
+
end
|
573
|
+
},
|
574
|
+
"Created" => lambda {|it| format_local_dt(it['dateCreated']) },
|
575
|
+
"Updated" => lambda {|it| format_local_dt(it['lastUpdated']) },
|
576
|
+
}
|
577
|
+
end
|
578
|
+
|
579
|
+
# this is not so simple, need to first choose select instance, host or provider
|
580
|
+
def add_deployment_version_option_types
|
281
581
|
[
|
282
|
-
{'fieldName' => '
|
283
|
-
{'fieldName' => '
|
582
|
+
{'fieldName' => 'userVersion', 'fieldLabel' => 'Version', 'type' => 'text', 'required' => true, 'displayOrder' => 1, 'description' => 'This is the deployment version identifier (userVersion)'},
|
583
|
+
{'fieldName' => 'deployType', 'fieldLabel' => 'Deploy Type', 'type' => 'select', 'optionSource' => 'deployTypes', 'required' => true, 'displayOrder' => 1, 'description' => 'This is the deployment version identifier (userVersion)', 'defaultValue' => 'file', 'code' => 'deployment.deployType'},
|
584
|
+
{'fieldName' => 'fetchUrl', 'fieldLabel' => 'Fetch URL', 'type' => 'select', 'optionSource' => 'deployTypes', 'required' => true, 'displayOrder' => 1, 'description' => 'The URL to fetch the deployment file(s) from.', 'dependsOnCode' => 'deployment.deployType:fetch'},
|
585
|
+
{'fieldName' => 'gitUrl', 'fieldLabel' => 'Git URL', 'type' => 'string', 'required' => true, 'displayOrder' => 1, 'description' => 'The URL to fetch the deployment file(s) from.', 'dependsOnCode' => 'deployment.deployType:git'},
|
586
|
+
{'fieldName' => 'gitRef', 'fieldLabel' => 'Git Ref', 'type' => 'string', 'displayOrder' => 1, 'description' => 'The Git Reference to use, this the branch or tag name, defaults to master.', 'dependsOnCode' => 'deployment.deployType:git'}
|
284
587
|
]
|
285
588
|
end
|
589
|
+
|
590
|
+
def add_deployment_version_advanced_option_types
|
591
|
+
[]
|
592
|
+
end
|
593
|
+
|
594
|
+
def update_deployment_version_option_types
|
595
|
+
add_deployment_version_option_types.collect {|it|
|
596
|
+
it.delete('required')
|
597
|
+
it.delete('defaultValue')
|
598
|
+
it
|
599
|
+
}
|
600
|
+
end
|
601
|
+
|
602
|
+
def update_deployment_version_advanced_option_types
|
603
|
+
add_deployment_version_advanced_option_types.collect {|it|
|
604
|
+
it.delete('required')
|
605
|
+
it.delete('defaultValue')
|
606
|
+
it
|
607
|
+
}
|
608
|
+
end
|
609
|
+
|
286
610
|
end
|