morpheus-cli 4.2.16 → 4.2.17
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 +43 -54
- 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 +3 -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/boot_scripts_command.rb +1 -1
- data/lib/morpheus/cli/cli_command.rb +92 -41
- 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 +51 -38
- 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/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/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 +1 -1
- 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
@@ -609,15 +609,6 @@ class Morpheus::Cli::Clusters
|
|
609
609
|
option_type_list = ((controller_type['optionTypes'].reject { |type| !type['enabled'] || type['fieldComponent'] } rescue []) + layout['optionTypes'] +
|
610
610
|
(cluster_type['optionTypes'].reject { |type| !type['enabled'] || !type['creatable'] || type['fieldComponent'] } rescue [])).sort { |type| type['displayOrder'] }
|
611
611
|
|
612
|
-
# remove volume options if volumes were configured
|
613
|
-
if !server_payload['volumes'].empty?
|
614
|
-
option_type_list = reject_volume_option_types(option_type_list)
|
615
|
-
end
|
616
|
-
# remove networkId option if networks were configured above
|
617
|
-
if !server_payload['networkInterfaces'].empty?
|
618
|
-
option_type_list = reject_networking_option_types(option_type_list)
|
619
|
-
end
|
620
|
-
|
621
612
|
server_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options], @api_client, {zoneId: cloud['id'], siteId: group['id'], layoutId: layout['id']}))
|
622
613
|
|
623
614
|
# Worker count
|
@@ -1197,15 +1188,6 @@ class Morpheus::Cli::Clusters
|
|
1197
1188
|
(type['fieldContext'] == 'instance.networkDomain' && type['fieldName'] == 'id')
|
1198
1189
|
} rescue [])
|
1199
1190
|
|
1200
|
-
# remove volume options if volumes were configured
|
1201
|
-
if !server_payload['volumes'].empty?
|
1202
|
-
option_type_list = reject_volume_option_types(option_type_list)
|
1203
|
-
end
|
1204
|
-
# remove networkId option if networks were configured above
|
1205
|
-
if !server_payload['networkInterfaces'].empty?
|
1206
|
-
option_type_list = reject_networking_option_types(option_type_list)
|
1207
|
-
end
|
1208
|
-
|
1209
1191
|
server_payload.deep_merge!(Morpheus::Cli::OptionTypes.prompt(option_type_list, options[:options], @api_client, {zoneId: cloud['id'], siteId: group['id'], layoutId: layout['id']}))
|
1210
1192
|
|
1211
1193
|
# Create User
|
@@ -363,7 +363,7 @@ EOT
|
|
363
363
|
else
|
364
364
|
out << "\texit: 0 "
|
365
365
|
end
|
366
|
-
total_time_str = "#{benchmark_record.duration.round((benchmark_record.duration > 0.002) ? 3 : 6)}s"
|
366
|
+
total_time_str = "#{benchmark_record.duration.round((benchmark_record.duration > 0.002) ? 3 : 6)} s"
|
367
367
|
out << "\t #{total_time_str.ljust(9, ' ')}"
|
368
368
|
else
|
369
369
|
benchmark_records = []
|
@@ -384,8 +384,8 @@ EOT
|
|
384
384
|
# all_durations = benchmark_records.collect {|benchmark_record| benchmark_record.duration }
|
385
385
|
# total_duration = all_durations.inject(0.0) {|acc, i| acc + i }
|
386
386
|
# avg_duration = total_duration / all_durations.size
|
387
|
-
# total_time_str = "#{total_duration.round((total_duration > 0.002) ? 3 : 6)}s"
|
388
|
-
# avg_time_str = "#{avg_duration.round((total_duration > 0.002) ? 3 : 6)}s"
|
387
|
+
# total_time_str = "#{total_duration.round((total_duration > 0.002) ? 3 : 6)} s"
|
388
|
+
# avg_time_str = "#{avg_duration.round((total_duration > 0.002) ? 3 : 6)} s"
|
389
389
|
|
390
390
|
all_durations = []
|
391
391
|
stats = {total: 0, avg: nil, min: nil, max: nil}
|
@@ -406,10 +406,10 @@ EOT
|
|
406
406
|
stats[:avg] = stats[:total].to_f / all_durations.size
|
407
407
|
end
|
408
408
|
|
409
|
-
total_time_str = "#{stats[:total].round((stats[:total] > 0.002) ? 3 : 6)}s"
|
410
|
-
min_time_str = stats[:min] ? "#{stats[:min].round((stats[:min] > 0.002) ? 3 : 6)}s" : ""
|
411
|
-
max_time_str = stats[:max] ? "#{stats[:max].round((stats[:max] > 0.002) ? 3 : 6)}s" : ""
|
412
|
-
avg_time_str = stats[:avg] ? "#{stats[:avg].round((stats[:avg] > 0.002) ? 3 : 6)}s" : ""
|
409
|
+
total_time_str = "#{stats[:total].round((stats[:total] > 0.002) ? 3 : 6)} s"
|
410
|
+
min_time_str = stats[:min] ? "#{stats[:min].round((stats[:min] > 0.002) ? 3 : 6)} s" : ""
|
411
|
+
max_time_str = stats[:max] ? "#{stats[:max].round((stats[:max] > 0.002) ? 3 : 6)} s" : ""
|
412
|
+
avg_time_str = stats[:avg] ? "#{stats[:avg].round((stats[:avg] > 0.002) ? 3 : 6)} s" : ""
|
413
413
|
|
414
414
|
out = ""
|
415
415
|
# <benchmark name or command>
|
@@ -176,7 +176,7 @@ morpheus v#{Morpheus::Cli::VERSION}
|
|
176
176
|
|
177
177
|
To learn more about the Morpheus Appliance, visit https://www.morpheusdata.com/features
|
178
178
|
|
179
|
-
To learn more about the Morpheus API, visit
|
179
|
+
To learn more about the Morpheus API, visit https://apidocs.morpheusdata.com
|
180
180
|
|
181
181
|
## GLOBAL OPTIONS
|
182
182
|
|
@@ -87,7 +87,7 @@ module Morpheus
|
|
87
87
|
rescue ::RestClient::Exception => e
|
88
88
|
#raise e
|
89
89
|
print_red_alert "Token not valid."
|
90
|
-
if options[:debug]
|
90
|
+
if options[:debug]
|
91
91
|
print_rest_exception(e, options)
|
92
92
|
end
|
93
93
|
wallet = nil
|
@@ -255,8 +255,7 @@ module Morpheus
|
|
255
255
|
true
|
256
256
|
end
|
257
257
|
|
258
|
-
def use_refresh_token(options = {})
|
259
|
-
#puts "use_refresh_token(#{options})"
|
258
|
+
def use_refresh_token(refresh_token_value, options = {})
|
260
259
|
|
261
260
|
wallet = load_saved_credentials
|
262
261
|
|
@@ -265,22 +264,25 @@ module Morpheus
|
|
265
264
|
return nil
|
266
265
|
end
|
267
266
|
|
268
|
-
if
|
269
|
-
|
270
|
-
|
267
|
+
if refresh_token_value.nil?
|
268
|
+
if wallet['refresh_token']
|
269
|
+
refresh_token_value = wallet['refresh_token']
|
270
|
+
else
|
271
|
+
print_red_alert yellow,"No refresh token found for #{display_appliance(@appliance_name, @appliance_url)}",reset,"\n"
|
272
|
+
return nil
|
273
|
+
end
|
271
274
|
end
|
272
275
|
|
273
|
-
|
274
276
|
username = wallet['username']
|
275
277
|
|
276
278
|
begin
|
277
279
|
auth_interface = Morpheus::AuthInterface.new({url:@appliance_url})
|
278
280
|
auth_interface.setopts(options)
|
279
281
|
if options[:dry_run]
|
280
|
-
print_dry_run auth_interface.dry.use_refresh_token(
|
282
|
+
print_dry_run auth_interface.dry.use_refresh_token(refresh_token_value)
|
281
283
|
return nil
|
282
284
|
end
|
283
|
-
json_response = auth_interface.use_refresh_token(
|
285
|
+
json_response = auth_interface.use_refresh_token(refresh_token_value)
|
284
286
|
#wallet = json_response
|
285
287
|
login_date = Time.now
|
286
288
|
expire_date = nil
|
@@ -311,6 +313,8 @@ module Morpheus
|
|
311
313
|
print_rest_exception(e, options)
|
312
314
|
end
|
313
315
|
wallet = nil
|
316
|
+
# return now or else it will log them out
|
317
|
+
return nil
|
314
318
|
end
|
315
319
|
|
316
320
|
# save wallet to credentials file
|
@@ -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
|