morpheus-cli 4.2.21 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/lib/morpheus/api/api_client.rb +30 -0
  4. data/lib/morpheus/api/billing_interface.rb +34 -0
  5. data/lib/morpheus/api/catalog_item_types_interface.rb +9 -0
  6. data/lib/morpheus/api/deploy_interface.rb +1 -1
  7. data/lib/morpheus/api/deployments_interface.rb +20 -1
  8. data/lib/morpheus/api/forgot_password_interface.rb +17 -0
  9. data/lib/morpheus/api/instances_interface.rb +16 -2
  10. data/lib/morpheus/api/rest_interface.rb +0 -6
  11. data/lib/morpheus/api/roles_interface.rb +14 -0
  12. data/lib/morpheus/api/search_interface.rb +13 -0
  13. data/lib/morpheus/api/servers_interface.rb +14 -0
  14. data/lib/morpheus/api/service_catalog_interface.rb +89 -0
  15. data/lib/morpheus/api/usage_interface.rb +18 -0
  16. data/lib/morpheus/cli.rb +7 -3
  17. data/lib/morpheus/cli/apps.rb +6 -27
  18. data/lib/morpheus/cli/backup_jobs_command.rb +3 -0
  19. data/lib/morpheus/cli/backups_command.rb +3 -0
  20. data/lib/morpheus/cli/catalog_item_types_command.rb +622 -0
  21. data/lib/morpheus/cli/cli_command.rb +70 -21
  22. data/lib/morpheus/cli/commands/standard/curl_command.rb +26 -12
  23. data/lib/morpheus/cli/commands/standard/history_command.rb +3 -1
  24. data/lib/morpheus/cli/commands/standard/man_command.rb +74 -40
  25. data/lib/morpheus/cli/commands/standard/source_command.rb +1 -1
  26. data/lib/morpheus/cli/commands/standard/update_command.rb +76 -0
  27. data/lib/morpheus/cli/containers_command.rb +14 -24
  28. data/lib/morpheus/cli/cypher_command.rb +6 -2
  29. data/lib/morpheus/cli/deploy.rb +199 -90
  30. data/lib/morpheus/cli/deployments.rb +341 -28
  31. data/lib/morpheus/cli/deploys.rb +206 -41
  32. data/lib/morpheus/cli/error_handler.rb +7 -0
  33. data/lib/morpheus/cli/forgot_password.rb +133 -0
  34. data/lib/morpheus/cli/groups.rb +1 -1
  35. data/lib/morpheus/cli/health_command.rb +59 -2
  36. data/lib/morpheus/cli/hosts.rb +265 -34
  37. data/lib/morpheus/cli/instances.rb +186 -100
  38. data/lib/morpheus/cli/invoices_command.rb +33 -16
  39. data/lib/morpheus/cli/jobs_command.rb +28 -6
  40. data/lib/morpheus/cli/library_option_lists_command.rb +15 -7
  41. data/lib/morpheus/cli/library_option_types_command.rb +5 -2
  42. data/lib/morpheus/cli/logs_command.rb +9 -6
  43. data/lib/morpheus/cli/mixins/accounts_helper.rb +12 -7
  44. data/lib/morpheus/cli/mixins/backups_helper.rb +2 -4
  45. data/lib/morpheus/cli/mixins/deployments_helper.rb +31 -3
  46. data/lib/morpheus/cli/mixins/option_source_helper.rb +1 -1
  47. data/lib/morpheus/cli/mixins/print_helper.rb +46 -21
  48. data/lib/morpheus/cli/mixins/provisioning_helper.rb +100 -4
  49. data/lib/morpheus/cli/network_pools_command.rb +14 -6
  50. data/lib/morpheus/cli/option_types.rb +271 -22
  51. data/lib/morpheus/cli/ping.rb +0 -1
  52. data/lib/morpheus/cli/remote.rb +35 -12
  53. data/lib/morpheus/cli/reports_command.rb +99 -30
  54. data/lib/morpheus/cli/roles.rb +453 -113
  55. data/lib/morpheus/cli/search_command.rb +182 -0
  56. data/lib/morpheus/cli/service_catalog_command.rb +1474 -0
  57. data/lib/morpheus/cli/service_plans_command.rb +2 -2
  58. data/lib/morpheus/cli/setup.rb +1 -1
  59. data/lib/morpheus/cli/shell.rb +33 -11
  60. data/lib/morpheus/cli/storage_providers_command.rb +40 -56
  61. data/lib/morpheus/cli/tasks.rb +29 -32
  62. data/lib/morpheus/cli/usage_command.rb +203 -0
  63. data/lib/morpheus/cli/user_settings_command.rb +1 -0
  64. data/lib/morpheus/cli/users.rb +12 -1
  65. data/lib/morpheus/cli/version.rb +1 -1
  66. data/lib/morpheus/cli/virtual_images.rb +429 -254
  67. data/lib/morpheus/cli/whoami.rb +6 -6
  68. data/lib/morpheus/cli/workflows.rb +34 -41
  69. data/lib/morpheus/formatters.rb +75 -7
  70. data/lib/morpheus/terminal.rb +6 -2
  71. metadata +14 -2
@@ -14,7 +14,7 @@ class Morpheus::Cli::SourceCommand
14
14
  optparse = Morpheus::Cli::OptionParser.new do|opts|
15
15
  opts.banner = "Usage: morpheus #{command_name} [file] [file2]"
16
16
  build_common_options(opts, options, [])
17
- opts.footer = "This will execute a file, treatin it as a script of morpheus commands"
17
+ opts.footer = "This will execute a file as a script where each line is a morpheus command or expression."
18
18
  end
19
19
  optparse.parse!(args)
20
20
  if args.count < 1
@@ -0,0 +1,76 @@
1
+ require 'morpheus/cli/cli_command'
2
+ require 'json'
3
+
4
+ # This is for use in dotfile scripts and the shell..
5
+ class Morpheus::Cli::UpdateCommand
6
+ include Morpheus::Cli::CliCommand
7
+ set_command_name :update
8
+
9
+ def handle(args)
10
+ options = {}
11
+ optparse = Morpheus::Cli::OptionParser.new do|opts|
12
+ opts.banner = "Usage: morpheus #{command_name}"
13
+ opts.on( '-f', '--force', "Force Update, executes update even if latest version is already installed." ) do
14
+ options[:force] = true
15
+ end
16
+ build_common_options(opts, options, [:dry_run, :quiet])
17
+ opts.footer = "This will update the morpheus command line interface to the latest version.\nThis is done by executing the system command: `gem update #{morpheus_gem_name}`"
18
+ end
19
+ optparse.parse!(args)
20
+ verify_args!(args:args, optparse:optparse, count:0)
21
+
22
+ current_version = Morpheus::Cli::VERSION
23
+ latest_version = get_latest_version()
24
+ latest_version = latest_version
25
+
26
+ if current_version == latest_version && !options[:force]
27
+ unless options[:quiet]
28
+ print cyan, "The latest version is already installed. (#{latest_version})", "\n", reset
29
+ end
30
+ return 0, nil
31
+ end
32
+
33
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm("Are you sure you want to update the #{morpheus_gem_name} gem from version #{current_version} to version #{latest_version}?")
34
+ return 9, "aborted command"
35
+ end
36
+
37
+ gem_update_command = "gem update #{morpheus_gem_name}"
38
+
39
+ if options[:dry_run]
40
+ unless options[:quiet]
41
+ print "\n"
42
+ print "#{cyan}#{bold}#{dark}COMMAND#{reset}\n"
43
+ puts gem_update_command
44
+ print "\n", reset
45
+ end
46
+ return 0, nil
47
+ end
48
+
49
+ # ok, update it
50
+ if options[:quiet]
51
+ system(gem_update_command)
52
+ else
53
+ `#{gem_update_command}`
54
+ end
55
+
56
+ if $?.success?
57
+ return 0, nil
58
+ else
59
+ return $?.exitstatus, "update failed"
60
+ end
61
+
62
+ end
63
+
64
+ protected
65
+
66
+ def morpheus_gem_name
67
+ 'morpheus-cli'
68
+ end
69
+
70
+ def get_latest_version
71
+ result = HTTP.get("https://rubygems.org/api/v1/gems/#{morpheus_gem_name}.json")
72
+ json_response = JSON.parse(result.body)
73
+ json_response["version"]
74
+ end
75
+
76
+ end
@@ -35,6 +35,9 @@ class Morpheus::Cli::ContainersCommand
35
35
  opts.on( nil, '--actions', "Display Available Actions" ) do
36
36
  options[:include_available_actions] = true
37
37
  end
38
+ opts.on( nil, '--costs', "Display Cost and Price" ) do
39
+ options[:include_costs] = true
40
+ end
38
41
  opts.on('--refresh [SECONDS]', String, "Refresh until status is running,failed. Default interval is #{default_refresh_interval} seconds.") do |val|
39
42
  options[:refresh_until_status] ||= "running,failed"
40
43
  if !val.to_s.empty?
@@ -99,6 +102,8 @@ class Morpheus::Cli::ContainersCommand
99
102
  "Name" => lambda {|it| it['server'] ? it['server']['name'] : '(no server)' }, # there is a server.displayName too?
100
103
  "Type" => lambda {|it| it['containerType'] ? it['containerType']['name'] : '' },
101
104
  "Plan" => lambda {|it| it['plan'] ? it['plan']['name'] : '' },
105
+ # "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
106
+ # "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
102
107
  "Instance" => lambda {|it| it['instance'] ? it['instance']['name'] : '' },
103
108
  "Host" => lambda {|it| it['server'] ? it['server']['name'] : '' },
104
109
  "Cloud" => lambda {|it| it['cloud'] ? it['cloud']['name'] : '' },
@@ -133,6 +138,15 @@ class Morpheus::Cli::ContainersCommand
133
138
  end
134
139
  end
135
140
 
141
+ if options[:include_costs]
142
+ print_h2 "Container Cost"
143
+ cost_columns = {
144
+ "Cost" => lambda {|it| it['hourlyCost'] ? format_money(it['hourlyCost'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
145
+ "Price" => lambda {|it| it['hourlyPrice'] ? format_money(it['hourlyPrice'], (it['currency'] || 'USD'), {sigdig:15}).to_s + ' per hour' : '' },
146
+ }
147
+ print_description_list(cost_columns, container)
148
+ end
149
+
136
150
  print reset, "\n"
137
151
 
138
152
  # refresh until a status is reached
@@ -685,28 +699,4 @@ private
685
699
  end
686
700
  end
687
701
 
688
- def format_container_status(container, return_color=cyan)
689
- out = ""
690
- status_string = container['status'].to_s
691
- if status_string == 'running'
692
- out << "#{green}#{status_string.upcase}#{return_color}"
693
- elsif status_string == 'stopped' or status_string == 'failed'
694
- out << "#{red}#{status_string.upcase}#{return_color}"
695
- elsif status_string == 'unknown'
696
- out << "#{white}#{status_string.upcase}#{return_color}"
697
- else
698
- out << "#{yellow}#{status_string.upcase}#{return_color}"
699
- end
700
- out
701
- end
702
-
703
- def format_container_connection_string(container)
704
- if !container['ports'].nil? && container['ports'].empty? == false
705
- connection_string = "#{container['ip']}:#{container['ports'][0]['external']}"
706
- else
707
- # eh? more logic needed here i think, see taglib morph:containerLocationMenu
708
- connection_string = "#{container['ip']}"
709
- end
710
- end
711
-
712
702
  end
@@ -265,6 +265,9 @@ EOT
265
265
  opts.on( '-v', '--value VALUE', "Secret value. This can be used to store a string instead of an object, and can also be passed as the second argument." ) do |val|
266
266
  item_value = val
267
267
  end
268
+ # opts.on( '--type VALUE', String, "Type, default is based on key engine, string or object" ) do |val|
269
+ # params['type'] = val
270
+ # end
268
271
  opts.on( '-t', '--ttl SECONDS', "Time to live, the lease duration before this key expires." ) do |val|
269
272
  ttl = val
270
273
  if val.to_s.empty? || val.to_s == '0'
@@ -276,7 +279,7 @@ EOT
276
279
  # opts.on( '--no-overwrite', '--no-overwrite', "Do not overwrite existing keys. Existing keys are overwritten by default." ) do
277
280
  # params['overwrite'] = false
278
281
  # end
279
- build_common_options(opts, options, [:auto_confirm, :options, :payload, :json, :yaml, :csv, :fields, :outfile, :dry_run, :quiet, :remote])
282
+ build_common_options(opts, options, [:auto_confirm, :options, :payload, :query, :json, :yaml, :csv, :fields, :outfile, :dry_run, :quiet, :remote])
280
283
  opts.footer = "Create or update a cypher key." + "\n" +
281
284
  "[key] is required. This is the key of the cypher being created or updated. The key includes the mount prefix eg. secret/hello" + "\n" +
282
285
  "[value] is required for some cypher engines, such as secret. This is the secret value or k=v pairs being stored. Supports 1-N arguments." + "\n" +
@@ -292,7 +295,8 @@ EOT
292
295
  # return 1
293
296
  # end
294
297
  connect(options)
295
-
298
+ params.merge!(parse_query_options(options))
299
+
296
300
  # parse arguments like [value] or [k=v]
297
301
  if args.count == 0
298
302
  # prompt for key and value
@@ -6,6 +6,7 @@ class Morpheus::Cli::Deploy
6
6
  include Morpheus::Cli::DeploymentsHelper
7
7
 
8
8
  set_command_name :deploy
9
+ set_command_description "Deploy to an instance from a morpheus.yml file."
9
10
 
10
11
  def connect(opts)
11
12
  @api_client = establish_remote_appliance_connection(opts)
@@ -18,30 +19,35 @@ class Morpheus::Cli::Deploy
18
19
  options={}
19
20
  optparse = Morpheus::Cli::OptionParser.new do|opts|
20
21
  opts.banner = "Usage: morpheus deploy [environment]"
21
- build_common_options(opts, options, [:auto_confirm, :remote, :dry_run])
22
+ build_common_options(opts, options, [:auto_confirm, :quiet, :remote, :dry_run])
22
23
  opts.footer = <<-EOT
23
24
  Deploy to an instance using the morpheus.yml file, located in the working directory.
24
25
  [environment] is optional. Merge settings under environments.{environment}. Default is no environment.
25
26
 
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.
27
+ First the morpheus.yml YAML file is parsed, merging the specified environment's nested settings.
28
+ The specified instance must exist and the specified deployment version must not exist.
29
+ If the settings are valid, the new deployment version will be created.
30
+ If is a file type deployment, all the discovered files are uploaded to the new deployment version.
31
+ Finally, it deploys the new version to the instance using any specified config options.
31
32
 
32
33
  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
+ This YAML file contains the settings that specify how to execute the deployment.
34
35
 
35
36
  File Settings
36
37
  ==================
37
38
 
38
- * name - (required) The instance name we are deploying to and, by default, name of the deployment being created.
39
+ * name - (required) The instance name being deployed to, also the default name of the deployment.
39
40
  * version - (required) The version identifier of the deployment being created (userVersion)
40
41
  * 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.
42
+ * type - The type of deployment, file, 'git' or 'fetch', default is 'file'.
43
+ * script - The initial script to run, happens before finding the files to be uploaded.
44
+ * files - (required) List of file patterns to use for uploading files and their target destination.
43
45
  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
46
+ only applies to type 'file'
47
+ * url - (required) The url to fetch files from, only applies to types 'git' and 'fetch'.
48
+ * ref - The git reference, default is master (main), only applies to type git.
49
+ * config - Map of deployment config options depending on deployment type
50
+ * options - alias for config
45
51
  * post_script - A post operation script to be run on the local machine
46
52
  * stage_only - If set to true the deploy will only be staged and not actually run
47
53
  * environments - Map of objects that contain nested properties for each environment name
@@ -51,7 +57,7 @@ It is possible to nest these properties in an "environments" map to override bas
51
57
  Example
52
58
  ==================
53
59
 
54
- name: neatsite
60
+ name: mysite
55
61
  version: 5.0
56
62
  script: "rake build"
57
63
  files:
@@ -60,6 +66,16 @@ environments:
60
66
  production:
61
67
  files:
62
68
  - path: production-build
69
+
70
+
71
+ Git Example
72
+ ==================
73
+
74
+ name: morpheus-apidoc
75
+ version: 5.0.0
76
+ type: git
77
+ url: "https://github.com/gomorpheus/morpheus-apidoc"
78
+
63
79
  EOT
64
80
  end
65
81
  optparse.parse!(args)
@@ -106,45 +122,90 @@ EOT
106
122
  instance = instance_results['instances'][0]
107
123
  instance_id = instance['id']
108
124
 
125
+ # auto detect type, default to file
126
+ deploy_type = deploy_args['type'] || deploy_args['deployType']
127
+ if deploy_type.nil?
128
+ if deploy_args['gitUrl']
129
+ deploy_type = 'git'
130
+ elsif deploy_args['fetchUrl'] || deploy_args['url']
131
+ deploy_type = 'fetch'
132
+ end
133
+ end
134
+ if deploy_type.nil?
135
+ deploy_type = "file"
136
+ end
137
+ deploy_url = deploy_args['url'] || deploy_args['fetchUrl'] || deploy_args['gitUrl']
138
+ if deploy_url.nil? && (deploy_type == "git" || deploy_type == "fetch")
139
+ raise_command_error "Deploy type '#{deploy_type}' requires a url to be specified"
140
+ end
141
+ #deploy_type = "file" if deploy_type.to_s.downcase == "files"
142
+
143
+ deploy_config = deploy_args['options'] || deploy_args['config']
144
+
109
145
  # ok do it
110
146
  # fetch/create deployment, create deployment version, upload files, and deploy it to instance.
111
147
 
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"
148
+ unless options[:quiet]
149
+
150
+ print_h1 "Morpheus Deployment", options
151
+
152
+ columns = {
153
+ "Instance" => :name,
154
+ "Deployment" => :deployment,
155
+ "Version" => :version,
156
+ "Deploy Type" => :type,
157
+ "Script" => :script,
158
+ "Post Script" => :post_script,
159
+ "Files" => :files,
160
+ "Git Url" => :git_url,
161
+ "Git Ref" => :git_ref,
162
+ "Fetch Url" => :fetch_url,
163
+ "Environment" => :environment,
164
+ }
165
+ pretty_file_config = deploy_args['files'] ? deploy_args['files'].collect {|it|
166
+ [(it['path'] ? "path: #{it['path']}" : nil), (it['pattern'] ? "pattern: #{it['pattern']}" : nil)].compact.join(", ")
167
+ }.join(", ") : "(none)"
168
+ deploy_settings = {
169
+ :name => instance_name,
170
+ :deployment => deployment_name,
171
+ :version => version_number,
172
+ :script => deploy_args['script'],
173
+ :post_script => deploy_args['post_script'],
174
+ :files => pretty_file_config,
175
+ :type => format_deploy_type(deploy_type),
176
+ :git_url => deploy_args['gitUrl'] || (deploy_type == "git" ? deploy_args['url'] : nil),
177
+ :git_ref => deploy_args['gitRef'] || (deploy_type == "git" ? deploy_args['ref'] : nil),
178
+ :fetch_url => deploy_args['fetchUrl'] || (deploy_type == "fetch" ? deploy_args['url'] : nil),
179
+ # :files => deploy_args['files'],
180
+ # :files => deploy_files.size,
181
+ # :file_config => (deploy_files.size == 1 ? deploy_files[0][:destination] : deploy_args['files'])
182
+ :environment => environment
183
+ }
184
+ columns.delete("Script") if deploy_settings[:script].nil?
185
+ columns.delete("Post Script") if deploy_settings[:post_script].nil?
186
+ columns.delete("Environment") if deploy_settings[:environment].nil?
187
+ columns.delete("Files") if deploy_type != "file" && deploy_type != "files"
188
+ columns.delete("Git Url") if deploy_settings[:git_url].nil?
189
+ columns.delete("Git Ref") if deploy_settings[:git_ref].nil?
190
+ columns.delete("Fetch Url") if deploy_settings[:fetch_url].nil?
191
+ print_description_list(columns, deploy_settings)
192
+ print reset, "\n"
193
+
194
+ if deploy_config
195
+ print_h2 "Config Options", options
196
+ print cyan
197
+ puts as_json(deploy_config)
198
+ print "\n\n", reset
199
+ end
200
+
201
+ end # unless options[:quiet]
143
202
 
144
203
  if !deploy_args['script'].nil?
145
204
  # 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']}"
205
+ unless options[:quiet]
206
+ print cyan, "Executing Pre Deploy Script...", reset, "\n"
207
+ puts "running command: #{deploy_args['script']}"
208
+ end
148
209
  if !system(deploy_args['script'])
149
210
  raise_command_error "Error executing pre script..."
150
211
  end
@@ -152,33 +213,71 @@ EOT
152
213
 
153
214
  # Find Files to Upload
154
215
  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}
216
+ if deploy_type == "file" || deploy_type == "files"
217
+ if deploy_args['files'].nil? || deploy_args['files'].empty? || !deploy_args['files'].is_a?(Array)
218
+ raise_command_error "Files not specified. Please specify the files to include, each item may specify a path or pattern of file(s) to upload"
219
+ else
220
+ #print "\n",cyan, "Finding Files...", reset, "\n"
221
+ current_working_dir = Dir.pwd
222
+ deploy_args['files'].each do |fmap|
223
+ Dir.chdir(fmap['path'] || current_working_dir)
224
+ files = Dir.glob(fmap['pattern'] || '**/*')
225
+ files.each do |file|
226
+ if File.file?(file)
227
+ destination = file.split("/")[0..-2].join("/")
228
+ # deploy_files << {filepath: File.expand_path(file), destination: destination}
229
+ deploy_files << {filepath: File.expand_path(file), destination: file}
230
+ end
168
231
  end
169
232
  end
233
+ #print cyan, "Found #{deploy_files.size} Files to Upload!", reset, "\n"
234
+ Dir.chdir(current_working_dir)
170
235
  end
171
- #print cyan, "Found #{deploy_files.size} Files to Upload!", reset, "\n"
172
- Dir.chdir(current_working_dir)
173
- end
174
236
 
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"
237
+ if deploy_files.empty?
238
+ raise_command_error "0 files found for: #{deploy_args['files'].inspect}"
239
+ else
240
+ unless options[:quiet]
241
+ print cyan, "Found #{deploy_files.size} Files to Upload!", reset, "\n"
242
+ end
243
+ end
244
+ elsif deploy_type == "git"
245
+ # make it work with simpler config, url instead of gitUrl
246
+ if deploy_args['gitUrl'].nil? && deploy_args['url']
247
+ deploy_args['gitUrl'] = deploy_args['url'] # .delete('url') maybe?
248
+ end
249
+ if deploy_args['gitRef'].nil? && deploy_args['ref']
250
+ deploy_args['gitRef'] = deploy_args['ref'] # .delete('ref') maybe?
251
+ end
252
+ if deploy_args['gitRef'].nil?
253
+ raise_command_error "fetchUrl not specified. Please specify the git url to fetch the deploy files from."
254
+ end
255
+ if deploy_args['gitRef'].nil?
256
+ #raise_command_error "gitRef not specified. Please specify the git reference to use. eg. main"
257
+ # deploy_args['gitRef'] = "main"
258
+ end
259
+ elsif deploy_type == "git"
260
+ # make it work with simpler config, url instead of fetchUrl
261
+ if deploy_args['fetchUrl'].nil? && deploy_args['url']
262
+ deploy_args['fetchUrl'] = deploy_args['url'] # .delete('url') maybe?
263
+ end
264
+ if deploy_args['fetchUrl'].nil?
265
+ raise_command_error "fetchUrl not specified. Please specify the url to fetch the deploy files from."
266
+ end
267
+
179
268
  end
180
269
 
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']}?")
270
+ confirm_warning = ""
271
+ confirm_message = "Are you sure you want to perform this action?"
272
+ if deploy_type == "file" || deploy_type == "files"
273
+ confirm_warning = "This will create deployment #{deployment_name} version #{version_number} and deploy it to instance #{instance['name']}."
274
+ elsif deploy_type == "git"
275
+ confirm_warning = "This will create deployment #{deployment_name} version #{version_number} and deploy it to instance #{instance['name']}."
276
+ elsif deploy_type == "fetch"
277
+ confirm_warning = "This will create deployment #{deployment_name} version #{version_number} and deploy it to instance #{instance['name']}."
278
+ end
279
+ puts confirm_warning if !options[:quiet]
280
+ unless options[:yes] || Morpheus::Cli::OptionTypes.confirm(confirm_message)
182
281
  return 9, "aborted command"
183
282
  end
184
283
 
@@ -242,7 +341,7 @@ EOT
242
341
  payload = {
243
342
  'version' => {
244
343
  'userVersion' => version_number,
245
- 'deployType' => (deploy_args['type'] || deploy_args['deployType'] || 'file')
344
+ 'deployType' => deploy_type
246
345
  }
247
346
  }
248
347
  payload['version']['fetchUrl'] = deploy_args['fetchUrl'] if deploy_args['fetchUrl']
@@ -261,31 +360,31 @@ EOT
261
360
 
262
361
 
263
362
  # 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]
363
+ if deploy_type == "file" || deploy_type == "files"
364
+ if deploy_files && !deploy_files.empty?
365
+ print "\n",cyan, "Uploading #{deploy_files.size} Files...", reset, "\n" if !options[:quiet]
366
+ current_working_dir = Dir.pwd
367
+ deploy_files.each do |f|
368
+ destination = f[:destination]
369
+ if options[:dry_run]
370
+ print_dry_run @deployments_interface.upload_file(deployment['id'], deployment_version['id'], f[:filepath], f[:destination])
371
+ else
372
+ print cyan," - Uploading #{f[:destination]} ...", reset if !options[:quiet]
373
+ upload_result = @deployments_interface.upload_file(deployment['id'], deployment_version['id'], f[:filepath], f[:destination])
374
+ #print green + "SUCCESS" + reset + "\n" if !options[:quiet]
375
+ print reset, "\n" if !options[:quiet]
376
+ end
276
377
  end
378
+ print cyan, "Upload Complete!", reset, "\n" if !options[:quiet]
379
+ Dir.chdir(current_working_dir)
380
+ else
381
+ print "\n",cyan, "0 files to upload", reset, "\n" if !options[:quiet]
277
382
  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
383
  end
283
384
 
284
- # TODO: support deploying other deployTypes too, git and fetch
285
-
286
385
  if !deploy_args['post_script'].nil?
287
- print cyan, "Executing Post Script...", reset, "\n"
288
- puts "running command: #{deploy_args['post_script']}"
386
+ print cyan, "Executing Post Script...", reset, "\n" if !options[:quiet]
387
+ puts "running command: #{deploy_args['post_script']}" if !options[:quiet]
289
388
  if !system(deploy_args['post_script'])
290
389
  raise_command_error "Error executing post script..."
291
390
  end
@@ -314,10 +413,14 @@ EOT
314
413
  end
315
414
  # stageOnly means do not actually deploy yet, can invoke @deploy_interface.deploy(deployment['id']) later
316
415
  # there is no cli command for that yet though..
317
- stage_only = deploy_args['stage_deploy'] || deploy_args['stage_only'] || deploy_args['stageOnly']
416
+ stage_only = deploy_args['stage'] || deploy_args['stage_deploy'] || deploy_args['stage_only'] || deploy_args['stageOnly']
318
417
  if stage_only
319
418
  payload['appDeploy']['stageOnly'] = true
320
419
  end
420
+ # config/options to apply to deployment
421
+ if deploy_config
422
+ payload['appDeploy']['config'] = deploy_config
423
+ end
321
424
  app_deploy_id = nil
322
425
  if options[:dry_run]
323
426
  print_dry_run @deploy_interface.dry.create(instance_id, payload)
@@ -325,11 +428,17 @@ EOT
325
428
  app_deploy_id = ':appDeployId'
326
429
  else
327
430
  # 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"
431
+ #print cyan, "Deploying #{deployment_name} version #{version_number} to instance #{instance_name} ...", reset, "\n"
329
432
  deploy_result = @deploy_interface.create(instance_id, payload)
330
433
  app_deploy = deploy_result['appDeploy']
331
434
  app_deploy_id = app_deploy['id']
332
- print_green_success "Deploy Successful!"
435
+ if !options[:quiet]
436
+ if app_deploy['status'] == 'staged'
437
+ print_green_success "Staged Deploy #{deployment_name} version #{version_number} to instance #{instance_name}"
438
+ else
439
+ print_green_success "Deploying #{deployment_name} version #{version_number} to instance #{instance_name}"
440
+ end
441
+ end
333
442
  end
334
443
  return 0, nil
335
444
  end