cpl 1.1.2 → 1.3.0

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check_cpln_links.yml +19 -0
  3. data/.github/workflows/rspec.yml +1 -1
  4. data/.overcommit.yml +3 -0
  5. data/CHANGELOG.md +47 -2
  6. data/CONTRIBUTING.md +2 -6
  7. data/Gemfile.lock +8 -8
  8. data/README.md +57 -15
  9. data/docs/commands.md +29 -23
  10. data/docs/dns.md +9 -0
  11. data/docs/migrating.md +3 -3
  12. data/examples/controlplane.yml +67 -4
  13. data/lib/command/apply_template.rb +2 -1
  14. data/lib/command/base.rb +62 -0
  15. data/lib/command/build_image.rb +5 -1
  16. data/lib/command/config.rb +0 -5
  17. data/lib/command/copy_image_from_upstream.rb +5 -4
  18. data/lib/command/delete.rb +40 -11
  19. data/lib/command/env.rb +1 -0
  20. data/lib/command/generate.rb +45 -0
  21. data/lib/command/info.rb +15 -33
  22. data/lib/command/latest_image.rb +1 -0
  23. data/lib/command/maintenance.rb +9 -4
  24. data/lib/command/maintenance_off.rb +8 -4
  25. data/lib/command/maintenance_on.rb +8 -4
  26. data/lib/command/no_command.rb +1 -0
  27. data/lib/command/ps.rb +5 -1
  28. data/lib/command/run.rb +20 -23
  29. data/lib/command/run_detached.rb +38 -30
  30. data/lib/command/setup_app.rb +3 -3
  31. data/lib/command/version.rb +1 -0
  32. data/lib/core/config.rb +194 -66
  33. data/lib/core/controlplane.rb +28 -7
  34. data/lib/core/controlplane_api.rb +13 -1
  35. data/lib/core/controlplane_api_direct.rb +18 -2
  36. data/lib/core/helpers.rb +16 -0
  37. data/lib/core/shell.rb +25 -3
  38. data/lib/cpl/version.rb +1 -1
  39. data/lib/cpl.rb +32 -3
  40. data/lib/generator_templates/Dockerfile +27 -0
  41. data/lib/generator_templates/controlplane.yml +57 -0
  42. data/lib/generator_templates/entrypoint.sh +8 -0
  43. data/lib/generator_templates/templates/gvc.yml +21 -0
  44. data/lib/generator_templates/templates/postgres.yml +176 -0
  45. data/lib/generator_templates/templates/rails.yml +36 -0
  46. data/script/check_cpln_links +45 -0
  47. metadata +14 -3
data/lib/command/base.rb CHANGED
@@ -1,9 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../core/helpers"
4
+
3
5
  module Command
4
6
  class Base # rubocop:disable Metrics/ClassLength
5
7
  attr_reader :config
6
8
 
9
+ include Helpers
10
+
7
11
  # Used to call the command (`cpl NAME`)
8
12
  # NAME = ""
9
13
  # Displayed when running `cpl help` or `cpl help NAME` (defaults to `NAME`)
@@ -15,6 +19,9 @@ module Command
15
19
  DEFAULT_ARGS = [].freeze
16
20
  # Options for the command (use option methods below)
17
21
  OPTIONS = [].freeze
22
+ # Does not throw error if `true` and extra options
23
+ # that are not specified in `OPTIONS` are passed to the command
24
+ ACCEPTS_EXTRA_OPTIONS = false
18
25
  # Displayed when running `cpl help`
19
26
  # DESCRIPTION = ""
20
27
  # Displayed when running `cpl help NAME`
@@ -23,6 +30,8 @@ module Command
23
30
  EXAMPLES = ""
24
31
  # If `true`, hides the command from `cpl help`
25
32
  HIDE = false
33
+ # Whether or not to show key information like ORG and APP name in commands
34
+ WITH_INFO_HEADER = true
26
35
 
27
36
  NO_IMAGE_AVAILABLE = "NO_IMAGE_AVAILABLE"
28
37
 
@@ -38,6 +47,10 @@ module Command
38
47
  end
39
48
  end
40
49
 
50
+ def self.common_options
51
+ [org_option, verbose_option, trace_option]
52
+ end
53
+
41
54
  def self.org_option(required: false)
42
55
  {
43
56
  name: :org,
@@ -103,6 +116,31 @@ module Command
103
116
  }
104
117
  end
105
118
 
119
+ def self.location_option(required: false)
120
+ {
121
+ name: :location,
122
+ params: {
123
+ aliases: ["-l"],
124
+ banner: "LOCATION_NAME",
125
+ desc: "Location name",
126
+ type: :string,
127
+ required: required
128
+ }
129
+ }
130
+ end
131
+
132
+ def self.domain_option(required: false)
133
+ {
134
+ name: :domain,
135
+ params: {
136
+ banner: "DOMAIN_NAME",
137
+ desc: "Domain name",
138
+ type: :string,
139
+ required: required
140
+ }
141
+ }
142
+ end
143
+
106
144
  def self.upstream_token_option(required: false)
107
145
  {
108
146
  name: :upstream_token,
@@ -188,6 +226,29 @@ module Command
188
226
  }
189
227
  end
190
228
 
229
+ def self.trace_option(required: false)
230
+ {
231
+ name: :trace,
232
+ params: {
233
+ desc: "Shows trace of API calls. WARNING: may contain sensitive data",
234
+ type: :boolean,
235
+ required: required
236
+ }
237
+ }
238
+ end
239
+
240
+ def self.clean_on_failure_option(required: false)
241
+ {
242
+ name: :clean_on_failure,
243
+ params: {
244
+ desc: "Deletes workload when finished with failure (success always deletes)",
245
+ type: :boolean,
246
+ required: required,
247
+ default: true
248
+ }
249
+ }
250
+ end
251
+
191
252
  def self.all_options
192
253
  methods.grep(/_option$/).map { |method| send(method.to_s) }
193
254
  end
@@ -239,6 +300,7 @@ module Command
239
300
  end
240
301
 
241
302
  def latest_image_next(app = config.app, org = config.org, commit: nil)
303
+ # debugger
242
304
  commit ||= config.options[:commit]
243
305
 
244
306
  @latest_image_next ||= {}
@@ -7,12 +7,14 @@ module Command
7
7
  app_option(required: true),
8
8
  commit_option
9
9
  ].freeze
10
+ ACCEPTS_EXTRA_OPTIONS = true
10
11
  DESCRIPTION = "Builds and pushes the image to Control Plane"
11
12
  LONG_DESCRIPTION = <<~DESC
12
13
  - Builds and pushes the image to Control Plane
13
14
  - Automatically assigns image numbers, e.g., `app:1`, `app:2`, etc.
14
15
  - Uses `.controlplane/Dockerfile` or a different Dockerfile specified through `dockerfile` in the `.controlplane/controlplane.yml` file
15
16
  - If a commit is provided through `--commit` or `-c`, it will be set as the runtime env var `GIT_COMMIT`
17
+ - Accepts extra options that are passed to `docker build`
16
18
  DESC
17
19
 
18
20
  def call # rubocop:disable Metrics/MethodLength
@@ -32,7 +34,9 @@ module Command
32
34
  build_args = []
33
35
  build_args.push("GIT_COMMIT=#{commit}") if commit
34
36
 
35
- cp.image_build(image_url, dockerfile: dockerfile, build_args: build_args)
37
+ cp.image_build(image_url, dockerfile: dockerfile,
38
+ docker_args: config.args,
39
+ build_args: build_args)
36
40
 
37
41
  progress.puts("\nPushed image to '/org/#{config.org}/image/#{image_name}'.")
38
42
  end
@@ -21,11 +21,6 @@ module Command
21
21
  EX
22
22
 
23
23
  def call # rubocop:disable Metrics/MethodLength
24
- if config.org_comes_from_env
25
- puts Shell.color("Org comes from CPLN_ORG env var", :yellow)
26
- puts
27
- end
28
-
29
24
  if config.app
30
25
  puts "#{Shell.color("Current config (app '#{config.app}')", :blue)}:"
31
26
  puts pretty_print(config.current)
@@ -11,7 +11,7 @@ module Command
11
11
  DESCRIPTION = "Copies an image (by default the latest) from a source org to the current org"
12
12
  LONG_DESCRIPTION = <<~DESC
13
13
  - Copies an image (by default the latest) from a source org to the current org
14
- - The source org must be specified through `upstream` in the `.controlplane/controlplane.yml` file
14
+ - The source app must be specified either through the `CPLN_UPSTREAM` env var or `upstream` in the `.controlplane/controlplane.yml` file
15
15
  - Additionally, the token for the source org must be provided through `--upstream-token` or `-t`
16
16
  - A `cpln` profile will be temporarily created to pull the image from the source org
17
17
  DESC
@@ -28,8 +28,8 @@ module Command
28
28
  def call # rubocop:disable Metrics/MethodLength
29
29
  ensure_docker_running!
30
30
 
31
- @upstream = config[:upstream]
32
- @upstream_org = config.apps[@upstream.to_sym][:cpln_org] || ENV.fetch("CPLN_ORG_UPSTREAM", nil)
31
+ @upstream = ENV.fetch("CPLN_UPSTREAM", nil) || config[:upstream]
32
+ @upstream_org = ENV.fetch("CPLN_ORG_UPSTREAM", nil) || config.find_app_config(@upstream)&.dig(:cpln_org)
33
33
  ensure_upstream_org!
34
34
 
35
35
  create_upstream_profile
@@ -38,6 +38,7 @@ module Command
38
38
  pull_image_from_upstream
39
39
  push_image_to_app
40
40
  ensure
41
+ cp.profile_switch("default")
41
42
  delete_upstream_profile
42
43
  end
43
44
 
@@ -60,7 +61,7 @@ module Command
60
61
  def create_upstream_profile
61
62
  step("Creating upstream profile") do
62
63
  loop do
63
- @upstream_profile = "upstream-#{rand(1000..9999)}"
64
+ @upstream_profile = "upstream-#{random_four_digits}"
64
65
  break unless cp.profile_exists?(@upstream_profile)
65
66
  end
66
67
 
@@ -7,21 +7,45 @@ module Command
7
7
  app_option(required: true),
8
8
  skip_confirm_option
9
9
  ].freeze
10
- DESCRIPTION = "Deletes the whole app (GVC with all workloads and all images)"
10
+ DESCRIPTION = "Deletes the whole app (GVC with all workloads, all volumesets and all images)"
11
11
  LONG_DESCRIPTION = <<~DESC
12
- - Deletes the whole app (GVC with all workloads and all images)
12
+ - Deletes the whole app (GVC with all workloads, all volumesets and all images)
13
13
  - Will ask for explicit user confirmation
14
14
  DESC
15
15
 
16
16
  def call
17
+ return progress.puts("App '#{config.app}' does not exist.") if cp.fetch_gvc.nil?
18
+
19
+ check_volumesets
20
+ check_images
17
21
  return unless confirm_delete
18
22
 
23
+ delete_volumesets
19
24
  delete_gvc
20
25
  delete_images
21
26
  end
22
27
 
23
28
  private
24
29
 
30
+ def check_volumesets
31
+ @volumesets = cp.fetch_volumesets["items"]
32
+ return progress.puts("No volumesets to delete.") unless @volumesets.any?
33
+
34
+ message = "The following volumesets will be deleted along with the app:"
35
+ volumesets_list = @volumesets.map { |volumeset| "- #{volumeset['name']}" }.join("\n")
36
+ progress.puts("#{Shell.color(message, :red)}\n#{volumesets_list}\n\n")
37
+ end
38
+
39
+ def check_images
40
+ @images = cp.query_images["items"]
41
+ .select { |image| image["name"].start_with?("#{config.app}:") }
42
+ return progress.puts("No images to delete.") unless @images.any?
43
+
44
+ message = "The following images will be deleted along with the app:"
45
+ images_list = @images.map { |image| "- #{image['name']}" }.join("\n")
46
+ progress.puts("#{Shell.color(message, :red)}\n#{images_list}\n\n")
47
+ end
48
+
25
49
  def confirm_delete
26
50
  return true if config.options[:yes]
27
51
 
@@ -33,22 +57,27 @@ module Command
33
57
  end
34
58
 
35
59
  def delete_gvc
36
- return progress.puts("App '#{config.app}' does not exist.") if cp.fetch_gvc.nil?
37
-
38
60
  step("Deleting app '#{config.app}'") do
39
61
  cp.gvc_delete
40
62
  end
41
63
  end
42
64
 
43
- def delete_images
44
- images = cp.query_images["items"]
45
- .filter_map { |item| item["name"] if item["name"].start_with?("#{config.app}:") }
65
+ def delete_volumesets
66
+ @volumesets.each do |volumeset|
67
+ step("Deleting volumeset '#{volumeset['name']}'") do
68
+ # If the volumeset is attached to a workload, we need to delete the workload first
69
+ workload = volumeset.dig("status", "usedByWorkload")&.split("/")&.last
70
+ cp.delete_workload(workload) if workload
46
71
 
47
- return progress.puts("No images to delete.") unless images.any?
72
+ cp.delete_volumeset(volumeset["name"])
73
+ end
74
+ end
75
+ end
48
76
 
49
- images.each do |image|
50
- step("Deleting image '#{image}'") do
51
- cp.image_delete(image)
77
+ def delete_images
78
+ @images.each do |image|
79
+ step("Deleting image '#{image['name']}'") do
80
+ cp.image_delete(image["name"])
52
81
  end
53
82
  end
54
83
  end
data/lib/command/env.rb CHANGED
@@ -10,6 +10,7 @@ module Command
10
10
  LONG_DESCRIPTION = <<~DESC
11
11
  - Displays app-specific environment variables
12
12
  DESC
13
+ WITH_INFO_HEADER = false
13
14
 
14
15
  def call
15
16
  cp.fetch_gvc!.dig("spec", "env").map do |prop|
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Command
4
+ class Generator < Thor::Group
5
+ include Thor::Actions
6
+
7
+ def copy_files
8
+ directory("generator_templates", ".controlplane")
9
+ end
10
+
11
+ def self.source_root
12
+ File.expand_path("../", __dir__)
13
+ end
14
+ end
15
+
16
+ class Generate < Base
17
+ NAME = "generate"
18
+ DESCRIPTION = "Creates base Control Plane config and template files"
19
+ LONG_DESCRIPTION = <<~DESC
20
+ Creates base Control Plane config and template files
21
+ DESC
22
+ EXAMPLES = <<~EX
23
+ ```sh
24
+ # Creates .controlplane directory with Control Plane config and other templates
25
+ cpl generate
26
+ ```
27
+ EX
28
+ WITH_INFO_HEADER = false
29
+
30
+ def call
31
+ if controlplane_directory_exists?
32
+ Shell.warn("The directory '.controlplane' already exists!")
33
+ return
34
+ end
35
+
36
+ Generator.start
37
+ end
38
+
39
+ private
40
+
41
+ def controlplane_directory_exists?
42
+ Dir.exist? ".controlplane"
43
+ end
44
+ end
45
+ end
data/lib/command/info.rb CHANGED
@@ -4,7 +4,6 @@ module Command
4
4
  class Info < Base # rubocop:disable Metrics/ClassLength
5
5
  NAME = "info"
6
6
  OPTIONS = [
7
- org_option,
8
7
  app_option
9
8
  ].freeze
10
9
  DESCRIPTION = "Displays the diff between defined/available apps/workloads (apps equal GVCs)"
@@ -17,7 +16,7 @@ module Command
17
16
  DESC
18
17
  EXAMPLES = <<~EX
19
18
  ```sh
20
- # Shows diff for all apps in all orgs.
19
+ # Shows diff for all apps in all orgs (based on `.controlplane/controlplane.yml`).
21
20
  cpl info
22
21
 
23
22
  # Shows diff for all apps in a specific org.
@@ -27,12 +26,13 @@ module Command
27
26
  cpl info -a $APP_NAME
28
27
  ```
29
28
  EX
29
+ WITH_INFO_HEADER = false
30
30
 
31
31
  def call
32
32
  @missing_apps_workloads = {}
33
33
  @missing_apps_starting_with = {}
34
34
 
35
- if config.app && !config.current[:match_if_app_name_starts_with]
35
+ if config.app && !config.should_app_start_with?(config.app)
36
36
  single_app_info
37
37
  else
38
38
  multiple_apps_info
@@ -41,20 +41,8 @@ module Command
41
41
 
42
42
  private
43
43
 
44
- def app_matches?(app, app_name, app_options)
45
- app == app_name.to_s || (app_options[:match_if_app_name_starts_with] && app.start_with?(app_name.to_s))
46
- end
47
-
48
- def find_app_options(app)
49
- @app_options ||= {}
50
- @app_options[app] ||= config.apps.find do |app_name, app_options|
51
- app_matches?(app, app_name, app_options)
52
- end&.last
53
- end
54
-
55
44
  def find_workloads(app)
56
- app_options = find_app_options(app)
57
- return [] if app_options.nil?
45
+ app_options = config.find_app_config(app)
58
46
 
59
47
  (app_options[:app_workloads] + app_options[:additional_workloads] + [app_options[:one_off_workload]]).uniq
60
48
  end
@@ -75,24 +63,19 @@ module Command
75
63
  end
76
64
 
77
65
  if config.app
78
- result.select { |app, _| app_matches?(app, config.app, config.current) }
66
+ result.select { |app, _| config.app_matches?(app, config.app, config.current) }
79
67
  else
80
- result.reject { |app, _| find_app_options(app).nil? }
68
+ result.reject { |app, _| config.find_app_config(app).nil? }
81
69
  end
82
70
  end
83
71
 
84
- def orgs # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
72
+ def orgs
85
73
  result = []
86
74
 
87
- if config.options[:org]
88
- result.push(config.options[:org])
75
+ if config.org
76
+ result.push(config.org)
89
77
  else
90
- org_from_env = ENV.fetch("CPLN_ORG", nil)
91
- result.push(org_from_env) if org_from_env
92
-
93
- config.apps.each do |app_name, app_options|
94
- next if config.app && !app_matches?(config.app, app_name, app_options)
95
-
78
+ config.apps.each do |_, app_options|
96
79
  org = app_options[:cpln_org]
97
80
  result.push(org) if org && !result.include?(org)
98
81
  end
@@ -105,7 +88,7 @@ module Command
105
88
  result = []
106
89
 
107
90
  config.apps.each do |app_name, app_options|
108
- next if config.app && !app_matches?(config.app, app_name, app_options)
91
+ next if config.app && !config.app_matches?(config.app, app_name, app_options)
109
92
 
110
93
  app_org = app_options[:cpln_org]
111
94
  result.push(app_name.to_s) if app_org == org
@@ -116,7 +99,7 @@ module Command
116
99
  end
117
100
 
118
101
  def any_app_starts_with?(app)
119
- @app_workloads.keys.find { |app_name| app_matches?(app_name, app, config.apps[app.to_sym]) }
102
+ @app_workloads.keys.find { |app_name| config.app_matches?(app_name, app, config.apps[app.to_sym]) }
120
103
  end
121
104
 
122
105
  def check_any_app_starts_with(app)
@@ -187,8 +170,7 @@ module Command
187
170
  "(replace 'whatever' with whatever suffix you want):"
188
171
 
189
172
  @missing_apps_starting_with.each do |app, _workloads|
190
- app_with_suffix = "#{app}#{app.end_with?('-') ? '' : '-'}whatever"
191
- puts " - `cpl setup-app -a #{app_with_suffix}`"
173
+ puts " - `cpl setup-app -a #{app}-whatever`"
192
174
  end
193
175
  end
194
176
 
@@ -200,7 +182,7 @@ module Command
200
182
  @defined_workloads = find_workloads(config.app)
201
183
  @available_workloads = fetch_workloads(config.app)
202
184
 
203
- workloads = (@defined_workloads + @available_workloads).uniq.sort
185
+ workloads = (@defined_workloads + @available_workloads).uniq
204
186
  workloads.each do |workload|
205
187
  print_workload(config.app, workload)
206
188
  end
@@ -220,7 +202,7 @@ module Command
220
202
  @defined_workloads = find_workloads(app)
221
203
  @available_workloads = @app_workloads[app] || []
222
204
 
223
- workloads = (@defined_workloads + @available_workloads).uniq.sort
205
+ workloads = (@defined_workloads + @available_workloads).uniq
224
206
  workloads.each do |workload|
225
207
  print_workload(app, workload)
226
208
  end
@@ -10,6 +10,7 @@ module Command
10
10
  LONG_DESCRIPTION = <<~DESC
11
11
  - Displays the latest image name
12
12
  DESC
13
+ WITH_INFO_HEADER = false
13
14
 
14
15
  def call
15
16
  puts latest_image
@@ -4,7 +4,8 @@ module Command
4
4
  class Maintenance < Base
5
5
  NAME = "maintenance"
6
6
  OPTIONS = [
7
- app_option(required: true)
7
+ app_option(required: true),
8
+ domain_option
8
9
  ].freeze
9
10
  DESCRIPTION = "Checks if maintenance mode is on or off for an app"
10
11
  LONG_DESCRIPTION = <<~DESC
@@ -14,20 +15,24 @@ module Command
14
15
  - Optionally specify the maintenance workload through `maintenance_workload` in the `.controlplane/controlplane.yml` file (defaults to 'maintenance')
15
16
  - Maintenance mode is only supported for domains that use path based routing mode and have a route configured for the prefix '/' on either port 80 or 443
16
17
  DESC
18
+ WITH_INFO_HEADER = false
17
19
 
18
20
  def call # rubocop:disable Metrics/MethodLength
19
21
  one_off_workload = config[:one_off_workload]
20
22
  maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21
23
 
22
- domain_data = cp.find_domain_for([one_off_workload, maintenance_workload])
24
+ domain_data = if config.domain
25
+ cp.fetch_domain(config.domain)
26
+ else
27
+ cp.find_domain_for([one_off_workload, maintenance_workload])
28
+ end
23
29
  unless domain_data
24
30
  raise "Can't find domain. " \
25
31
  "Maintenance mode is only supported for domains that use path based routing mode " \
26
32
  "and have a route configured for the prefix '/' on either port 80 or 443."
27
33
  end
28
34
 
29
- domain_workload = cp.get_domain_workload(domain_data)
30
- if domain_workload == maintenance_workload
35
+ if cp.domain_workload_matches?(domain_data, maintenance_workload)
31
36
  puts "on"
32
37
  else
33
38
  puts "off"
@@ -4,7 +4,8 @@ module Command
4
4
  class MaintenanceOff < Base
5
5
  NAME = "maintenance:off"
6
6
  OPTIONS = [
7
- app_option(required: true)
7
+ app_option(required: true),
8
+ domain_option
8
9
  ].freeze
9
10
  DESCRIPTION = "Disables maintenance mode for an app"
10
11
  LONG_DESCRIPTION = <<~DESC
@@ -18,7 +19,11 @@ module Command
18
19
  one_off_workload = config[:one_off_workload]
19
20
  maintenance_workload = config.current[:maintenance_workload] || "maintenance"
20
21
 
21
- domain_data = cp.find_domain_for([one_off_workload, maintenance_workload])
22
+ domain_data = if config.domain
23
+ cp.fetch_domain(config.domain)
24
+ else
25
+ cp.find_domain_for([one_off_workload, maintenance_workload])
26
+ end
22
27
  unless domain_data
23
28
  raise "Can't find domain. " \
24
29
  "Maintenance mode is only supported for domains that use path based routing mode " \
@@ -26,8 +31,7 @@ module Command
26
31
  end
27
32
 
28
33
  domain = domain_data["name"]
29
- domain_workload = cp.get_domain_workload(domain_data)
30
- if domain_workload == one_off_workload
34
+ if cp.domain_workload_matches?(domain_data, one_off_workload)
31
35
  progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
32
36
  return
33
37
  end
@@ -4,7 +4,8 @@ module Command
4
4
  class MaintenanceOn < Base
5
5
  NAME = "maintenance:on"
6
6
  OPTIONS = [
7
- app_option(required: true)
7
+ app_option(required: true),
8
+ domain_option
8
9
  ].freeze
9
10
  DESCRIPTION = "Enables maintenance mode for an app"
10
11
  LONG_DESCRIPTION = <<~DESC
@@ -18,7 +19,11 @@ module Command
18
19
  one_off_workload = config[:one_off_workload]
19
20
  maintenance_workload = config.current[:maintenance_workload] || "maintenance"
20
21
 
21
- domain_data = cp.find_domain_for([one_off_workload, maintenance_workload])
22
+ domain_data = if config.domain
23
+ cp.fetch_domain(config.domain)
24
+ else
25
+ cp.find_domain_for([one_off_workload, maintenance_workload])
26
+ end
22
27
  unless domain_data
23
28
  raise "Can't find domain. " \
24
29
  "Maintenance mode is only supported for domains that use path based routing mode " \
@@ -26,8 +31,7 @@ module Command
26
31
  end
27
32
 
28
33
  domain = domain_data["name"]
29
- domain_workload = cp.get_domain_workload(domain_data)
30
- if domain_workload == maintenance_workload
34
+ if cp.domain_workload_matches?(domain_data, maintenance_workload)
31
35
  progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
32
36
  return
33
37
  end
@@ -9,6 +9,7 @@ module Command
9
9
  - Called when no command was specified
10
10
  DESC
11
11
  HIDE = true
12
+ WITH_INFO_HEADER = false
12
13
 
13
14
  def call
14
15
  if config.options[:version]
data/lib/command/ps.rb CHANGED
@@ -5,6 +5,7 @@ module Command
5
5
  NAME = "ps"
6
6
  OPTIONS = [
7
7
  app_option(required: true),
8
+ location_option,
8
9
  workload_option
9
10
  ].freeze
10
11
  DESCRIPTION = "Shows running replicas in app"
@@ -20,16 +21,19 @@ module Command
20
21
  cpl ps -a $APP_NAME -w $WORKLOAD_NAME
21
22
  ```
22
23
  EX
24
+ WITH_INFO_HEADER = false
23
25
 
24
26
  def call
25
27
  cp.fetch_gvc!
26
28
 
29
+ location = config.location
30
+
27
31
  workloads = [config.options[:workload]] if config.options[:workload]
28
32
  workloads ||= config[:app_workloads] + config[:additional_workloads]
29
33
  workloads.each do |workload|
30
34
  cp.fetch_workload!(workload)
31
35
 
32
- result = cp.workload_get_replicas(workload, location: config[:default_location])
36
+ result = cp.workload_get_replicas(workload, location: location)
33
37
  result["items"].each { |replica| puts replica }
34
38
  end
35
39
  end