cpflow 3.0.1 → 4.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 305f8dddc321aed06da473ca199d7411a40ed8bf3498ba09b4f7d77b1fb2f554
4
- data.tar.gz: 9656d940052e40e1914a7930606022b5acc75483aa10b1fe144e4ed9a68ac4d9
3
+ metadata.gz: 48de117fc2fbc2458b8469bfb3d93663c2950777803f84079dfdfa7cdbcda9e9
4
+ data.tar.gz: e3a8347bd330f6df7d2d5e98a3692144fa04d3c935241fbacf7ab06c8f039e79
5
5
  SHA512:
6
- metadata.gz: 1a51e614265cbbc86f89251ed5a8a8804d9caabe316301c26d0d839c80713b583726fae91f2c24bb1b778caaff23e6156f027a9b051c892816fe788b1ead5e8a
7
- data.tar.gz: 75a834c607df1cefce11f509059c60ae6db790a2be7a9217cc054401f30b855be0a388e61ecce56413929ea2cd24a0b479ce3e474c964127e134f571cd816690
6
+ metadata.gz: '06907b1c67896b14b71376bc88253fcd74a675fb088aab8f6c7bf051ebfaf3f463c3ab96bf33bf64abe6da5bf1dff22529503508176a6d1fc5c35517021c9dc4'
7
+ data.tar.gz: ae76127106fa6dc3544669163e94571d68ec149f22b8ed68d1cf0332c3f333b65e1a1d2f6f6b2cb75039d45bcf1f8418f1cb4d5ceba750cf11cc930ac5d38ac4
@@ -3,19 +3,22 @@ name: RSpec Shared
3
3
  on:
4
4
  workflow_call:
5
5
  inputs:
6
- os-version:
6
+ os_version:
7
7
  required: true
8
8
  type: string
9
- ruby-version:
9
+ ruby_version:
10
10
  required: true
11
11
  type: string
12
- test-tag:
13
- required: true
12
+ test_tag:
13
+ required: false
14
+ type: string
15
+ spec_paths:
16
+ required: false
14
17
  type: string
15
18
 
16
19
  jobs:
17
20
  rspec:
18
- runs-on: ${{ inputs.os-version }}
21
+ runs-on: ${{ inputs.os_version }}
19
22
  env:
20
23
  RAILS_ENV: test
21
24
  # We have to add "_CI" to the end, otherwise it messes with tests where we switch profiles,
@@ -28,7 +31,7 @@ jobs:
28
31
  - name: Set up Ruby
29
32
  uses: ruby/setup-ruby@v1
30
33
  with:
31
- ruby-version: ${{ inputs.ruby-version }}
34
+ ruby-version: ${{ inputs.ruby_version }}
32
35
  bundler-cache: true
33
36
  - name: Install dependencies
34
37
  run: bundle install
@@ -41,16 +44,16 @@ jobs:
41
44
  cpln profile create default --token $CPLN_TOKEN_CI --org $CPLN_ORG
42
45
  cpln image docker-login
43
46
  - name: Run tests
44
- run: bundle exec rspec --format documentation --tag ${{ inputs.test-tag }}
47
+ run: bundle exec rspec --format documentation ${{ inputs.test_tag && format('--tag {0}', inputs.test_tag) }} ${{ inputs.spec_paths }}
45
48
  - name: Upload spec log
46
49
  uses: actions/upload-artifact@master
47
50
  if: always()
48
51
  with:
49
- name: spec-${{ inputs.test-tag }}-${{ github.run_id }}-${{ inputs.os-version }}-${{ inputs.ruby-version }}.log
52
+ name: spec-${{ inputs.test_tag }}-${{ github.run_id }}-${{ inputs.os_version }}-${{ inputs.ruby_version }}.log
50
53
  path: spec.log
51
54
  - name: Upload coverage results
52
55
  uses: actions/upload-artifact@master
53
56
  if: always()
54
57
  with:
55
- name: coverage-report-${{ inputs.test-tag }}-${{ github.run_id }}-${{ inputs.os-version }}-${{ inputs.ruby-version }}
58
+ name: coverage-report-${{ inputs.test_tag }}-${{ github.run_id }}-${{ inputs.os_version }}-${{ inputs.ruby_version }}
56
59
  path: coverage
@@ -0,0 +1,18 @@
1
+ name: RSpec Specific
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ spec_paths:
7
+ description: "Test files or directories that should be run"
8
+ required: true
9
+
10
+ jobs:
11
+ rspec-specific:
12
+ name: RSpec (Specific)
13
+ uses: ./.github/workflows/rspec-shared.yml
14
+ with:
15
+ os_version: ubuntu-latest
16
+ ruby_version: "3.2"
17
+ spec_paths: ${{ inputs.spec_paths }}
18
+ secrets: inherit
@@ -12,9 +12,9 @@ jobs:
12
12
  name: RSpec (Fast)
13
13
  uses: ./.github/workflows/rspec-shared.yml
14
14
  with:
15
- os-version: ubuntu-latest
16
- ruby-version: "3.2"
17
- test-tag: ~slow
15
+ os_version: ubuntu-latest
16
+ ruby_version: "3.2"
17
+ test_tag: ~slow
18
18
  secrets: inherit
19
19
 
20
20
  rspec-slow:
@@ -22,7 +22,7 @@ jobs:
22
22
  uses: ./.github/workflows/rspec-shared.yml
23
23
  if: github.event_name == 'workflow_dispatch'
24
24
  with:
25
- os-version: ubuntu-latest
26
- ruby-version: "3.2"
27
- test-tag: slow
25
+ os_version: ubuntu-latest
26
+ ruby_version: "3.2"
27
+ test_tag: slow
28
28
  secrets: inherit
data/.overcommit.yml CHANGED
@@ -10,7 +10,7 @@ PreCommit:
10
10
  on_warn: fail
11
11
  command: ["bundle", "exec", "rubocop"]
12
12
 
13
- PrePush:
14
- RSpec:
15
- enabled: true
16
- command: ["bundle", "exec", "rspec"]
13
+ # PrePush:
14
+ # RSpec:
15
+ # enabled: true
16
+ # command: ["bundle", "exec", "rspec"]
data/.rubocop.yml CHANGED
@@ -20,3 +20,7 @@ RSpec/ExampleLength:
20
20
 
21
21
  RSpec/MultipleExpectations:
22
22
  Enabled: false
23
+
24
+ RSpec/NestedGroups:
25
+ Enabled: true
26
+ Max: 5
data/CHANGELOG.md CHANGED
@@ -14,12 +14,34 @@ Changes since the last non-beta release.
14
14
 
15
15
  _Please add entries here for your pull requests that have not yet been released._
16
16
 
17
+ ### Fixed
18
+
19
+ - Fixed issue where `run` command fails when runner workload has ENV but original workload does not. [PR 227](https://github.com/shakacode/control-plane-flow/pull/227) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
20
+
21
+ - Fixed potential infinite loop that could occur for a command if one of the execution steps fails and gets stuck. [PR 217](https://github.com/shakacode/control-plane-flow/pull/217) by [Zakir Dzhamaliddinov](https://github.com/zzaakiirr).
22
+
23
+ ## [4.0.0] - 2024-08-21
24
+
25
+ ### Fixed
26
+
27
+ - Fixed issue where common options are not forwarded to other commands. [PR 207](https://github.com/shakacode/control-plane-flow/pull/207) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
28
+ - Fixed BYOK endpoint. [PR 209](https://github.com/shakacode/control-plane-flow/pull/209) by [Sergey Tarasov](https://github.com/dzirtusss).
29
+ - Fixed issue where `generate` command fails if no project config exists. [PR 219](https://github.com/shakacode/control-plane-flow/pull/219) by [Zakir Dzhamaliddinov](https://github.com/zzaakiirr).
30
+ - Bumped min `cpln` version to `3.1.0` and fixed `cpln workload exec` calls. [PR 226](https://github.com/shakacode/control-plane-flow/pull/226) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
31
+
32
+ ## [3.0.1] - 2024-06-26
33
+
34
+ ### Fixed
35
+
36
+ - Moved development dependencies to Gemfile and updated many of them. [PR 208](https://github.com/shakacode/control-plane-flow/pull/208) by [Justin Gordon](https://github.com/justin808).
37
+
38
+ ## [3.0.0] - 2024-06-21
17
39
 
18
- ## [3.0.0] - 2024-06-20
19
40
  First release of `cpflow`.
20
41
 
21
- ## [2.2.4] - 2024-06-20
22
- Deprecate `cpl` CLI. New gem is `cpflow`
42
+ ## [2.2.4] - 2024-06-21
43
+
44
+ Deprecated `cpl` gem. New gem is `cpflow`.
23
45
 
24
46
  ## [2.2.1] - 2024-06-17
25
47
 
@@ -64,17 +86,17 @@ Deprecate `cpl` CLI. New gem is `cpflow`
64
86
  - Specific validations are now run before commands, and the command will exit with a non-zero code if any validation fails. Can be disabled by setting `DISABLE_VALIDATIONS` env var to `true`. [PR 185](https://github.com/shakacode/control-plane-flow/pull/185) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
65
87
  - Deprecated the `--skip-secret-access-binding` option in favor of `--skip-secrets-setup`. This can also now be configured through `skip_secrets_setup` in `controlplane.yml` [PR 190](https://github.com/shakacode/control-plane-flow/pull/190) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
66
88
 
67
- ## [2.0.2] - 2024-05-17
89
+ ## [2.0.2] - 2024-05-18
68
90
 
69
91
  - Fixed issue with improper handling of job statuses. Fixed issue with interactive magic string showing and exit code. [PR 177](https://github.com/shakacode/control-plane-flow/pull/177) by [Sergey Tarasov](https://github.com/dzirtusss).
70
92
 
71
- ## [2.0.1] - 2024-05-15
93
+ ## [2.0.1] - 2024-05-16
72
94
 
73
95
  ### Fixed
74
96
 
75
97
  - Fixed issue where `cleanup-stale-apps` command fails to delete apps with volumesets. [PR 175](https://github.com/shakacode/control-plane-flow/pull/175) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
76
98
 
77
- ## [2.0.0] - 2024-05-14
99
+ ## [2.0.0] - 2024-05-15
78
100
 
79
101
  ### BREAKING CHANGES
80
102
 
@@ -104,7 +126,7 @@ Deprecate `cpl` CLI. New gem is `cpflow`
104
126
  - `deploy-image` command now raises an error if image does not exist. [PR 153](https://github.com/shakacode/control-plane-flow/pull/153) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
105
127
  - `delete` command now unbinds identity from policy (if bound) when deleting app. [PR 170](https://github.com/shakacode/control-plane-flow/pull/170) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
106
128
 
107
- ## [1.4.0] - 2024-03-20
129
+ ## [1.4.0] - 2024-03-21
108
130
 
109
131
  ### Added
110
132
 
@@ -141,12 +163,12 @@ Deprecate `cpl` CLI. New gem is `cpflow`
141
163
  - `info` command now lists workloads in the same order as `controlplane.yml`. [PR 139](https://github.com/shakacode/control-plane-flow/pull/139) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
142
164
  - Improved domain workload matching for `maintenance`, `maintenance:on` and `maintenance:off` commands (instead of matching only by workload, it now matches by org + app + workload, which is more accurate). [PR 140](https://github.com/shakacode/control-plane-flow/pull/140) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
143
165
 
144
- ## [1.2.0] - 2024-01-03
166
+ ## [1.2.0] - 2024-01-04
145
167
 
146
168
  ### Fixed
147
169
 
148
170
  - Fixed issue where `info` command does not respect `CPLN_ORG` env var. [PR 88](https://github.com/shakacode/control-plane-flow/pull/88) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
149
- - Fixed issues with running `cpflow --version` and `cpflow --help` where no configuration file exists. [PR 100](https://github.com/shakacode/control-plane-flow/pull/100) by [Mostafa Ahangarha](https://github.com/ahangarha).
171
+ - Fixed issues with running `cpflow --version` and `cpflow --help` where no configuration file exists. [PR 109](https://github.com/shakacode/control-plane-flow/pull/109) by [Mostafa Ahangarha](https://github.com/ahangarha).
150
172
  - Fixed issue where `delete` command fails to delete apps with volumesets. [PR 123](https://github.com/shakacode/control-plane-flow/pull/123) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
151
173
 
152
174
  ### Added
@@ -157,19 +179,19 @@ Deprecate `cpl` CLI. New gem is `cpflow`
157
179
  - Added option to only use `CPLN_ORG` and `CPLN_APP` env vars if `allow_org_override_by_env` and `allow_app_override_by_env` configs are set to `true` in `controlplane.yml`. [PR 109](https://github.com/shakacode/control-plane-flow/pull/109) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
158
180
  - Added `CPLN_LOCATION` env variable and `--location` option for `apply-template`, `ps`, `run`, `run:detached`. [PR 105](https://github.com/shakacode/control-plane-flow/pull/105) by [Mostafa Ahangarha](https://github.com/ahangarha).
159
181
  - Added `generate` command for creating basic Control Plane configuration directory. [PR 116](https://github.com/shakacode/control-plane-flow/pull/116) by [Mostafa Ahangarhga](https://github.com/ahangarha).
160
- - Added `--trace` option to all commands for more detailed logs. [PR 124](https://github.com/shakacode/control-plane-flow/pull/124) by [justin808](https://github.com/justin808)
161
- - Added better error message to check the org name in case of a 403 error. [PR 124](https://github.com/justin808) by [justin808](https://github.com/justin808)
182
+ - Added `--trace` option to all commands for more detailed logs. [PR 124](https://github.com/shakacode/control-plane-flow/pull/124) by [Justin Gordon](https://github.com/justin808).
183
+ - Added better error message to check the org name in case of a 403 error. [PR 124](https://github.com/shakacode/control-plane-flow/pull/124) by [Justin Gordon](https://github.com/justin808).
162
184
 
163
185
  ### Changed
164
186
 
165
187
  - `--org` option now takes precedence over `CPLN_ORG` env var, which takes precedence over `cpln_org` from `controlplane.yml`. [PR 88](https://github.com/shakacode/control-plane-flow/pull/88) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
166
188
  - Renamed `setup` config into `setup_app_templates`. [PR 112](https://github.com/shakacode/control-plane-flow/pull/112) by [Mostafa Ahangarha](https://github.com/ahangarha).
167
189
 
168
- ## [1.1.2] - 2023-10-17
190
+ ## [1.1.2] - 2023-10-25
169
191
 
170
192
  ### Fixed
171
193
 
172
- - Fixed failed build on MacOS by adding platform flag and fixed multiple files in yaml document for template. [PR 81](https://github.com/shakacode/control-plane-flow/pull/81) by [justin808](https://github.com/justin808).
194
+ - Fixed failed build on MacOS by adding platform flag and fixed multiple files in yaml document for template. [PR 81](https://github.com/shakacode/control-plane-flow/pull/81) by [Justin Gordon](https://github.com/justin808).
173
195
 
174
196
  ### Added
175
197
 
@@ -181,7 +203,7 @@ Deprecate `cpl` CLI. New gem is `cpflow`
181
203
 
182
204
  - Calling `cpflow` with no command now shows the help menu. [PR 83](https://github.com/shakacode/control-plane-flow/pull/83) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
183
205
 
184
- ## [1.1.1] - 2023-09-23
206
+ ## [1.1.1] - 2023-09-21
185
207
 
186
208
  ### Fixed
187
209
 
@@ -205,7 +227,7 @@ Deprecate `cpl` CLI. New gem is `cpflow`
205
227
  - Renamed `cleanup-old-images` command to `cleanup-images`. [PR 72](https://github.com/shakacode/control-plane-flow/pull/72) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
206
228
  - Renamed `old_image_retention_days` config to `image_retention_days`. [PR 72](https://github.com/shakacode/control-plane-flow/pull/72) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
207
229
 
208
- ## [1.0.4] - 2023-07-21
230
+ ## [1.0.4] - 2023-07-24
209
231
 
210
232
  ### Fixed
211
233
 
@@ -244,9 +266,11 @@ Deprecate `cpl` CLI. New gem is `cpflow`
244
266
 
245
267
  ## [1.0.0] - 2023-05-29
246
268
 
247
- - Initial release
269
+ First release.
248
270
 
249
- [Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v3.0.0...HEAD
271
+ [Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v4.0.0...HEAD
272
+ [4.0.0]: https://github.com/shakacode/control-plane-flow/compare/v3.0.1...v4.0.0
273
+ [3.0.1]: https://github.com/shakacode/control-plane-flow/compare/v3.0.0...v3.0.1
250
274
  [3.0.0]: https://github.com/shakacode/control-plane-flow/compare/v2.2.4...v3.0.0
251
275
  [2.2.4]: https://github.com/shakacode/control-plane-flow/compare/v2.2.1...v2.2.4
252
276
  [2.2.1]: https://github.com/shakacode/control-plane-flow/compare/v2.2.0...v2.2.1
data/CONTRIBUTING.md CHANGED
@@ -64,7 +64,7 @@ CPLN_ORG=your-org-for-tests bundle exec rspec --tag slow
64
64
  2. Use the `--trace` option to see full logging of HTTP requests. Warning, this will display keys to your logs or console.
65
65
  1. Add a breakpoint (`debugger`) to any line of code you want to debug.
66
66
  2. Modify the `lib/command/test.rb` file to trigger the code you want to test. To simulate a command, you can use
67
- `Cpflow::Cli.start` (e.g., `Cpflow::Cli.start(["deploy-image", "-a", "my-app-name"])` would be the same as running
67
+ `run_cpflow_command` (e.g., `run_cpflow_command("deploy-image", "-a", "my-app-name")` would be the same as running
68
68
  `cpflow deploy-image -a my-app-name`).
69
69
  3. Run the `test` command in your test app with a `.controlplane` directory.
70
70
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cpflow (3.0.1)
4
+ cpflow (4.0.1)
5
5
  dotenv (~> 2.8.1)
6
6
  jwt (~> 2.8.1)
7
7
  psych (~> 5.1.0)
@@ -43,7 +43,7 @@ module Command
43
43
  VALIDATIONS = %w[config templates].freeze
44
44
 
45
45
  def call # rubocop:disable Metrics/MethodLength
46
- @template_parser = TemplateParser.new(config)
46
+ @template_parser = TemplateParser.new(self)
47
47
  @names_to_filenames = config.args.to_h do |name|
48
48
  [name, @template_parser.template_filename(name)]
49
49
  end
data/lib/command/base.rb CHANGED
@@ -465,45 +465,50 @@ module Command
465
465
  $stderr
466
466
  end
467
467
 
468
- def step_error(error, abort_on_error: true)
469
- message = error.message
470
- if abort_on_error
471
- progress.puts(" #{Shell.color('failed!', :red)}\n\n")
472
- Shell.abort(message)
473
- else
474
- Shell.write_to_tmp_stderr(message)
475
- end
476
- end
477
-
478
- def step_finish(success)
468
+ def step_finish(success, abort_on_error: true)
479
469
  if success
480
470
  progress.puts(" #{Shell.color('done!', :green)}")
481
471
  else
482
472
  progress.puts(" #{Shell.color('failed!', :red)}\n\n#{Shell.read_from_tmp_stderr}\n\n")
473
+ exit(ExitCode::ERROR_DEFAULT) if abort_on_error
483
474
  end
484
475
  end
485
476
 
486
- def step(message, abort_on_error: true, retry_on_failure: false) # rubocop:disable Metrics/MethodLength
477
+ def step(message, abort_on_error: true, retry_on_failure: false, max_retry_count: 1000, wait: 1, &block) # rubocop:disable Metrics/MethodLength
487
478
  progress.print("#{message}...")
488
479
 
489
480
  Shell.use_tmp_stderr do
490
481
  success = false
491
482
 
492
483
  begin
493
- if retry_on_failure
494
- until (success = yield)
495
- progress.print(".")
496
- Kernel.sleep(1)
484
+ success =
485
+ if retry_on_failure
486
+ with_retry(max_retry_count: max_retry_count, wait: wait, &block)
487
+ else
488
+ yield
497
489
  end
498
- else
499
- success = yield
500
- end
501
490
  rescue RuntimeError => e
502
- step_error(e, abort_on_error: abort_on_error)
491
+ Shell.write_to_tmp_stderr(e.message)
503
492
  end
504
493
 
505
- step_finish(success)
494
+ step_finish(success, abort_on_error: abort_on_error)
495
+ end
496
+ end
497
+
498
+ def with_retry(max_retry_count:, wait:)
499
+ retry_count = 0
500
+ success = false
501
+
502
+ while !success && retry_count <= max_retry_count
503
+ success = yield
504
+ break if success
505
+
506
+ progress.print(".")
507
+ Kernel.sleep(wait)
508
+ retry_count += 1
506
509
  end
510
+
511
+ success
507
512
  end
508
513
 
509
514
  def cp
@@ -527,7 +532,7 @@ module Command
527
532
  progress.puts("Running #{title}...\n\n")
528
533
 
529
534
  begin
530
- Cpflow::Cli.start(["run", "-a", config.app, "--image", "latest", "--", command])
535
+ run_cpflow_command("run", "-a", config.app, "--image", "latest", "--", command)
531
536
  rescue SystemExit => e
532
537
  progress.puts
533
538
 
@@ -536,5 +541,19 @@ module Command
536
541
  progress.puts("Finished running #{title}.\n\n")
537
542
  end
538
543
  end
544
+
545
+ def run_cpflow_command(command, *args)
546
+ common_args = []
547
+
548
+ self.class.common_options.each do |option|
549
+ value = config.options[option[:name]]
550
+ next if value.nil?
551
+
552
+ name = "--#{option[:name].to_s.tr('_', '-')}"
553
+ common_args.push(name, value)
554
+ end
555
+
556
+ Cpflow::Cli.start([command, *common_args, *args])
557
+ end
539
558
  end
540
559
  end
@@ -38,7 +38,11 @@ module Command
38
38
  docker_args: config.args,
39
39
  build_args: build_args)
40
40
 
41
- progress.puts("\nPushed image to '/org/#{config.org}/image/#{image_name}'.\n\n")
41
+ push_path = "/org/#{config.org}/image/#{image_name}"
42
+
43
+ progress.puts("\nPushing image to '#{push_path}'...\n\n")
44
+ cp.image_push(image_url)
45
+ progress.puts("\nPushed image to '#{push_path}'.\n\n")
42
46
 
43
47
  step("Waiting for image to be available", retry_on_failure: true) do
44
48
  images = cp.query_images["items"]
@@ -73,7 +73,7 @@ module Command
73
73
  end
74
74
 
75
75
  def delete_app(app)
76
- Cpflow::Cli.start(["delete", "-a", app, "--yes"])
76
+ run_cpflow_command("delete", "-a", app, "--yes")
77
77
  end
78
78
  end
79
79
  end
@@ -35,7 +35,7 @@ module Command
35
35
  container_name = container["name"]
36
36
  step("Deploying image '#{image}' for workload '#{container_name}'") do
37
37
  cp.workload_set_image_ref(workload, container: container_name, image: image)
38
- deployed_endpoints[container_name] = workload_data.dig("status", "endpoint")
38
+ deployed_endpoints[container_name] = endpoint_for_workload(workload_data)
39
39
  end
40
40
  end
41
41
  end
@@ -48,6 +48,15 @@ module Command
48
48
 
49
49
  private
50
50
 
51
+ def endpoint_for_workload(workload_data)
52
+ endpoint = workload_data.dig("status", "endpoint")
53
+ Resolv.getaddress(endpoint.split("/").last)
54
+ endpoint
55
+ rescue Resolv::ResolvError
56
+ deployments = cp.fetch_workload_deployments(workload_data["name"])
57
+ deployments.dig("items", 0, "status", "endpoint")
58
+ end
59
+
51
60
  def run_release_script
52
61
  release_script = config[:release_script]
53
62
  run_command_in_latest_image(release_script, title: "release script")
@@ -29,7 +29,7 @@ module Command
29
29
  validations = config.options[:validations].split(",")
30
30
  ensure_required_options!(validations)
31
31
 
32
- doctor_service = DoctorService.new(config)
32
+ doctor_service = DoctorService.new(self)
33
33
  doctor_service.run_validations(validations)
34
34
  end
35
35
 
@@ -26,6 +26,7 @@ module Command
26
26
  ```
27
27
  EX
28
28
  WITH_INFO_HEADER = false
29
+ VALIDATIONS = [].freeze
29
30
 
30
31
  def call
31
32
  if controlplane_directory_exists?
@@ -17,26 +17,14 @@ module Command
17
17
  DESC
18
18
  WITH_INFO_HEADER = false
19
19
 
20
- def call # rubocop:disable Metrics/MethodLength
21
- one_off_workload = config[:one_off_workload]
22
- maintenance_workload = config.current[:maintenance_workload] || "maintenance"
20
+ def call
21
+ puts maintenance_mode.enabled? ? "on" : "off"
22
+ end
23
23
 
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
29
- unless domain_data
30
- raise "Can't find domain. " \
31
- "Maintenance mode is only supported for domains that use path based routing mode " \
32
- "and have a route configured for the prefix '/' on either port 80 or 443."
33
- end
24
+ private
34
25
 
35
- if cp.domain_workload_matches?(domain_data, maintenance_workload)
36
- puts "on"
37
- else
38
- puts "off"
39
- end
26
+ def maintenance_mode
27
+ @maintenance_mode ||= MaintenanceMode.new(self)
40
28
  end
41
29
  end
42
30
  end
@@ -15,48 +15,14 @@ module Command
15
15
  - 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
16
  DESC
17
17
 
18
- def call # rubocop:disable Metrics/MethodLength
19
- one_off_workload = config[:one_off_workload]
20
- maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21
-
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
27
- unless domain_data
28
- raise "Can't find domain. " \
29
- "Maintenance mode is only supported for domains that use path based routing mode " \
30
- "and have a route configured for the prefix '/' on either port 80 or 443."
31
- end
32
-
33
- domain = domain_data["name"]
34
- if cp.domain_workload_matches?(domain_data, one_off_workload)
35
- progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
36
- return
37
- end
38
-
39
- cp.fetch_workload!(maintenance_workload)
40
-
41
- # Start all other workloads
42
- Cpflow::Cli.start(["ps:start", "-a", config.app, "--wait"])
43
-
44
- progress.puts
45
-
46
- # Switch domain workload
47
- step("Switching workload for domain '#{domain}' to '#{one_off_workload}'") do
48
- cp.set_domain_workload(domain_data, one_off_workload)
49
-
50
- # Give it a bit of time for the domain to update
51
- Kernel.sleep(30)
52
- end
53
-
54
- progress.puts
18
+ def call
19
+ maintenance_mode.disable!
20
+ end
55
21
 
56
- # Stop maintenance workload
57
- Cpflow::Cli.start(["ps:stop", "-a", config.app, "-w", maintenance_workload, "--wait"])
22
+ private
58
23
 
59
- progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
24
+ def maintenance_mode
25
+ @maintenance_mode ||= MaintenanceMode.new(self)
60
26
  end
61
27
  end
62
28
  end
@@ -15,48 +15,14 @@ module Command
15
15
  - 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
16
  DESC
17
17
 
18
- def call # rubocop:disable Metrics/MethodLength
19
- one_off_workload = config[:one_off_workload]
20
- maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21
-
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
27
- unless domain_data
28
- raise "Can't find domain. " \
29
- "Maintenance mode is only supported for domains that use path based routing mode " \
30
- "and have a route configured for the prefix '/' on either port 80 or 443."
31
- end
32
-
33
- domain = domain_data["name"]
34
- if cp.domain_workload_matches?(domain_data, maintenance_workload)
35
- progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
36
- return
37
- end
38
-
39
- cp.fetch_workload!(maintenance_workload)
40
-
41
- # Start maintenance workload
42
- Cpflow::Cli.start(["ps:start", "-a", config.app, "-w", maintenance_workload, "--wait"])
43
-
44
- progress.puts
45
-
46
- # Switch domain workload
47
- step("Switching workload for domain '#{domain}' to '#{maintenance_workload}'") do
48
- cp.set_domain_workload(domain_data, maintenance_workload)
49
-
50
- # Give it a bit of time for the domain to update
51
- Kernel.sleep(30)
52
- end
53
-
54
- progress.puts
18
+ def call
19
+ maintenance_mode.enable!
20
+ end
55
21
 
56
- # Stop all other workloads
57
- Cpflow::Cli.start(["ps:stop", "-a", config.app, "--wait"])
22
+ private
58
23
 
59
- progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
24
+ def maintenance_mode
25
+ @maintenance_mode ||= MaintenanceMode.new(self)
60
26
  end
61
27
  end
62
28
  end
@@ -14,9 +14,9 @@ module Command
14
14
 
15
15
  def call
16
16
  if config.options[:version]
17
- Cpflow::Cli.start(["version"])
17
+ run_cpflow_command("version")
18
18
  else
19
- Cpflow::Cli.start(["help"])
19
+ run_cpflow_command("help")
20
20
  end
21
21
  end
22
22
  end
@@ -25,14 +25,14 @@ module Command
25
25
  private
26
26
 
27
27
  def copy_image_from_upstream
28
- Cpflow::Cli.start(["copy-image-from-upstream", "-a", config.app, "-t", config.options[:upstream_token]])
28
+ run_cpflow_command("copy-image-from-upstream", "-a", config.app, "-t", config.options[:upstream_token])
29
29
  progress.puts
30
30
  end
31
31
 
32
32
  def deploy_image
33
33
  args = []
34
34
  args.push("--run-release-phase") if config.current[:release_script]
35
- Cpflow::Cli.start(["deploy-image", "-a", config.app, *args])
35
+ run_cpflow_command("deploy-image", "-a", config.app, *args)
36
36
  end
37
37
  end
38
38
  end
data/lib/command/run.rb CHANGED
@@ -207,7 +207,7 @@ module Command
207
207
  original_env_str = original_container_spec["env"]&.sort_by { |env| env["name"] }.to_s
208
208
  env_str = container_spec["env"]&.sort_by { |env| env["name"] }.to_s
209
209
  if original_env_str != env_str
210
- container_spec["env"] = original_container_spec["env"]
210
+ container_spec["env"] = original_container_spec["env"] || []
211
211
  should_update = true
212
212
  end
213
213
 
@@ -243,7 +243,7 @@ module Command
243
243
 
244
244
  step("Updating runner workload '#{runner_workload}'") do
245
245
  # Update runner workload
246
- @expected_deployed_version = cp.cron_workload_deployed_version(runner_workload) + 1
246
+ @expected_deployed_version = (cp.cron_workload_deployed_version(runner_workload) || 0) + 1
247
247
  cp.apply_hash("kind" => "workload", "name" => runner_workload, "spec" => spec)
248
248
  end
249
249
  end
@@ -256,7 +256,7 @@ module Command
256
256
 
257
257
  def wait_for_runner_workload_update
258
258
  step("Waiting for runner workload '#{runner_workload}' to be updated", retry_on_failure: true) do
259
- cp.cron_workload_deployed_version(runner_workload) >= expected_deployed_version
259
+ (cp.cron_workload_deployed_version(runner_workload) || 0) >= expected_deployed_version
260
260
  end
261
261
  end
262
262
 
@@ -306,7 +306,7 @@ module Command
306
306
  exit(ExitCode::SUCCESS)
307
307
  end
308
308
 
309
- Cpflow::Cli.start(["logs", *app_workload_replica_args])
309
+ run_cpflow_command("logs", *app_workload_replica_args)
310
310
  end
311
311
  Process.detach(logs_pid)
312
312
 
@@ -42,7 +42,7 @@ module Command
42
42
 
43
43
  args = []
44
44
  args.push("--add-app-identity") unless skip_secrets_setup
45
- Cpflow::Cli.start(["apply-template", *templates, "-a", config.app, *args])
45
+ run_cpflow_command("apply-template", *templates, "-a", config.app, *args)
46
46
 
47
47
  bind_identity_to_policy unless skip_secrets_setup
48
48
  run_post_creation_hook unless config.options[:skip_post_creation_hook]
data/lib/command/test.rb CHANGED
@@ -16,8 +16,8 @@ module Command
16
16
  def call
17
17
  # Modify this method to trigger the code you want to test.
18
18
  # You can use `debugger` to debug.
19
- # You can use `Cpflow::Cli.start` to simulate a command
20
- # (e.g., `Cpflow::Cli.start(["deploy-image", "-a", "my-app-name"])`).
19
+ # You can use `run_cpflow_command` to simulate a command
20
+ # (e.g., `run_cpflow_command("deploy-image", "-a", "my-app-name")`).
21
21
  end
22
22
  end
23
23
  end
@@ -90,7 +90,7 @@ class Controlplane # rubocop:disable Metrics/ClassLength
90
90
  api.query_images(org: a_org, gvc: a_gvc, gvc_op_type: gvc_op)
91
91
  end
92
92
 
93
- def image_build(image, dockerfile:, docker_args: [], build_args: [], push: true)
93
+ def image_build(image, dockerfile:, docker_args: [], build_args: [])
94
94
  # https://docs.controlplane.com/guides/push-image#step-2
95
95
  # Might need to use `docker buildx build` if compatiblitity issues arise
96
96
  cmd = "docker build --platform=linux/amd64 -t #{image} -f #{dockerfile}"
@@ -99,9 +99,8 @@ class Controlplane # rubocop:disable Metrics/ClassLength
99
99
  cmd += " #{docker_args.join(' ')}" if docker_args.any?
100
100
  build_args.each { |build_arg| cmd += " --build-arg #{build_arg}" }
101
101
  cmd += " #{config.app_dir}"
102
- perform!(cmd)
103
102
 
104
- image_push(image) if push
103
+ perform!(cmd)
105
104
  end
106
105
 
107
106
  def fetch_image_details(image)
@@ -278,7 +277,7 @@ class Controlplane # rubocop:disable Metrics/ClassLength
278
277
  end
279
278
 
280
279
  def workload_exec(workload, replica, location:, container: nil, command: nil)
281
- cmd = "cpln workload exec #{workload} #{gvc_org} --replica #{replica} --location #{location}"
280
+ cmd = "cpln workload exec #{workload} #{gvc_org} --replica #{replica} --location #{location} -it"
282
281
  cmd += " --container #{container}" if container
283
282
  cmd += " -- #{command}"
284
283
  perform!(cmd, output_mode: :all)
@@ -3,10 +3,12 @@
3
3
  class ValidationError < StandardError; end
4
4
 
5
5
  class DoctorService
6
- attr_reader :config
6
+ extend Forwardable
7
7
 
8
- def initialize(config)
9
- @config = config
8
+ def_delegators :@command, :config, :progress
9
+
10
+ def initialize(command)
11
+ @command = command
10
12
  end
11
13
 
12
14
  def run_validations(validations, silent_if_passing: false) # rubocop:disable Metrics/MethodLength
@@ -37,7 +39,7 @@ class DoctorService
37
39
  end
38
40
 
39
41
  def validate_templates
40
- @template_parser = TemplateParser.new(config)
42
+ @template_parser = TemplateParser.new(@command)
41
43
  filenames = Dir.glob("#{@template_parser.template_dir}/*.yml")
42
44
  templates = @template_parser.parse(filenames)
43
45
 
@@ -97,8 +99,4 @@ class DoctorService
97
99
  .join("\n")
98
100
  progress.puts("\n#{Shell.color("DEPRECATED: #{message}", :yellow)}\n#{list}\n\n")
99
101
  end
100
-
101
- def progress
102
- $stderr
103
- end
104
102
  end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MaintenanceMode
4
+ extend Forwardable
5
+
6
+ def_delegators :@command, :config, :progress, :cp, :step, :run_cpflow_command
7
+
8
+ def initialize(command)
9
+ @command = command
10
+ end
11
+
12
+ def enabled?
13
+ validate_domain_exists!
14
+ cp.domain_workload_matches?(domain_data, maintenance_workload)
15
+ end
16
+
17
+ def disabled?
18
+ validate_domain_exists!
19
+ cp.domain_workload_matches?(domain_data, one_off_workload)
20
+ end
21
+
22
+ def enable!
23
+ if enabled?
24
+ progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
25
+ else
26
+ enable_maintenance_mode
27
+ end
28
+ end
29
+
30
+ def disable!
31
+ if disabled?
32
+ progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
33
+ else
34
+ disable_maintenance_mode
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def enable_maintenance_mode
41
+ validate_maintenance_workload_exists!
42
+
43
+ start_or_stop_maintenance_workload(:start)
44
+ switch_domain_workload(to: maintenance_workload)
45
+ start_or_stop_all_workloads(:stop)
46
+
47
+ progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
48
+ end
49
+
50
+ def disable_maintenance_mode
51
+ validate_maintenance_workload_exists!
52
+
53
+ start_or_stop_maintenance_workload(:start)
54
+ switch_domain_workload(to: one_off_workload)
55
+ start_or_stop_all_workloads(:stop)
56
+
57
+ progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
58
+ end
59
+
60
+ def validate_domain_exists!
61
+ return if domain_data
62
+
63
+ raise "Can't find domain. " \
64
+ "Maintenance mode is only supported for domains that use path based routing mode " \
65
+ "and have a route configured for the prefix '/' on either port 80 or 443."
66
+ end
67
+
68
+ def validate_maintenance_workload_exists!
69
+ cp.fetch_workload!(maintenance_workload)
70
+ end
71
+
72
+ def start_or_stop_all_workloads(action)
73
+ run_cpflow_command("ps:#{action}", "-a", config.app, "--wait")
74
+
75
+ progress.puts
76
+ end
77
+
78
+ def start_or_stop_maintenance_workload(action)
79
+ run_cpflow_command("ps:#{action}", "-a", config.app, "-w", maintenance_workload, "--wait")
80
+
81
+ progress.puts
82
+ end
83
+
84
+ def switch_domain_workload(to:)
85
+ step("Switching workload for domain '#{domain_data['name']}' to '#{to}'") do
86
+ cp.set_domain_workload(domain_data, to)
87
+
88
+ # Give it a bit of time for the domain to update
89
+ Kernel.sleep(30)
90
+ end
91
+
92
+ progress.puts
93
+ end
94
+
95
+ def domain_data
96
+ @domain_data ||=
97
+ if config.domain
98
+ cp.fetch_domain(config.domain)
99
+ else
100
+ cp.find_domain_for([one_off_workload, maintenance_workload])
101
+ end
102
+ end
103
+
104
+ def one_off_workload
105
+ @one_off_workload ||= config[:one_off_workload]
106
+ end
107
+
108
+ def maintenance_workload
109
+ @maintenance_workload ||= config.current[:maintenance_workload] || "maintenance"
110
+ end
111
+ end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TemplateParser
4
- attr_reader :config, :deprecated_variables
4
+ extend Forwardable
5
5
 
6
- def initialize(config)
7
- @config = config
6
+ def_delegators :@command, :config, :cp
7
+
8
+ attr_reader :deprecated_variables
9
+
10
+ def initialize(command)
11
+ @command = command
8
12
  end
9
13
 
10
14
  def template_dir
@@ -69,8 +73,4 @@ class TemplateParser
69
73
  "APP_IMAGE" => "{{APP_IMAGE}}"
70
74
  }
71
75
  end
72
-
73
- def cp
74
- @cp ||= Controlplane.new(config)
75
- end
76
76
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cpflow
4
- VERSION = "3.0.1"
5
- MIN_CPLN_VERSION = "2.0.1"
4
+ VERSION = "4.0.1"
5
+ MIN_CPLN_VERSION = "3.1.0"
6
6
  end
data/lib/cpflow.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "date"
4
+ require "forwardable"
4
5
  require "dotenv/load"
5
6
  require "cgi"
6
7
  require "json"
@@ -30,25 +31,7 @@ at_exit do
30
31
  end
31
32
  end
32
33
 
33
- # Fix for https://github.com/erikhuda/thor/issues/398
34
- # Copied from https://github.com/rails/thor/issues/398#issuecomment-622988390
35
- class Thor
36
- module Shell
37
- class Basic
38
- def print_wrapped(message, options = {})
39
- indent = (options[:indent] || 0).to_i
40
- if indent.zero?
41
- stdout.puts(message)
42
- else
43
- message.each_line do |message_line|
44
- stdout.print(" " * indent)
45
- stdout.puts(message_line.chomp)
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
34
+ require_relative "patches/thor"
52
35
 
53
36
  module Cpflow
54
37
  class Error < StandardError; end
@@ -226,12 +209,14 @@ module Cpflow
226
209
 
227
210
  Cpflow::Cli.show_info_header(config) if with_info_header
228
211
 
212
+ command = command_class.new(config)
213
+
229
214
  if validations.any? && ENV.fetch("DISABLE_VALIDATIONS", nil) != "true"
230
- doctor = DoctorService.new(config)
215
+ doctor = DoctorService.new(command)
231
216
  doctor.run_validations(validations, silent_if_passing: true)
232
217
  end
233
218
 
234
- command_class.new(config).call
219
+ command.call
235
220
  rescue RuntimeError => e
236
221
  ::Shell.abort(e.message)
237
222
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Thor
4
+ # Fix for https://github.com/erikhuda/thor/issues/398
5
+ # Copied from https://github.com/rails/thor/issues/398#issuecomment-622988390
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ indent = (options[:indent] || 0).to_i
10
+ if indent.zero?
11
+ stdout.puts(message)
12
+ else
13
+ message.each_line do |message_line|
14
+ stdout.print(" " * indent)
15
+ stdout.puts(message_line.chomp)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ # Fix for https://github.com/rails/thor/issues/742
23
+ def self.basename
24
+ @package_name || super
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpflow
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-06-26 00:00:00.000000000 Z
12
+ date: 2024-08-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dotenv
@@ -79,6 +79,7 @@ files:
79
79
  - ".github/workflows/check_cpln_links.yml"
80
80
  - ".github/workflows/command_docs.yml"
81
81
  - ".github/workflows/rspec-shared.yml"
82
+ - ".github/workflows/rspec-specific.yml"
82
83
  - ".github/workflows/rspec.yml"
83
84
  - ".github/workflows/rubocop.yml"
84
85
  - ".gitignore"
@@ -148,6 +149,7 @@ files:
148
149
  - lib/core/controlplane_api_direct.rb
149
150
  - lib/core/doctor_service.rb
150
151
  - lib/core/helpers.rb
152
+ - lib/core/maintenance_mode.rb
151
153
  - lib/core/shell.rb
152
154
  - lib/core/template_parser.rb
153
155
  - lib/cpflow.rb
@@ -159,6 +161,7 @@ files:
159
161
  - lib/generator_templates/templates/app.yml
160
162
  - lib/generator_templates/templates/postgres.yml
161
163
  - lib/generator_templates/templates/rails.yml
164
+ - lib/patches/thor.rb
162
165
  - rakelib/create_release.rake
163
166
  - script/add_command
164
167
  - script/check_command_docs