cpl 2.1.0 → 2.2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -1
- data/Gemfile.lock +2 -2
- data/README.md +12 -0
- data/docs/commands.md +7 -2
- data/examples/controlplane.yml +12 -0
- data/lib/command/ps_wait.rb +7 -3
- data/lib/command/run.rb +87 -34
- data/lib/core/controlplane.rb +5 -0
- data/lib/cpl/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27661f3a2e2aff2f7018e2cb0e77835ee4de88a8ee0268ec549cafa9d02dfbaa
|
4
|
+
data.tar.gz: 001a114b051c3501b5449eb6d3e4c9f7dea3fa608c6e4595e2129c3bcad8f855
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38dfd9ca9aa2d28dc7df577677e5732f37740448beb857269ff156da7a8ff2f8627872c958b63e9d1d308ce091df1376e44c09aff96bc82f128edb887e1aba94
|
7
|
+
data.tar.gz: 14c73bf485166dd5be51ff276b6cef8aa3152bb0482fd92b6752e47575cd43ab0bd620ba1c49de619863cff955b628477eb32188a8f76393423c50b1a81e5b07
|
data/CHANGELOG.md
CHANGED
@@ -16,6 +16,22 @@ _Please add entries here for your pull requests that have not yet been released.
|
|
16
16
|
|
17
17
|
### Fixed
|
18
18
|
|
19
|
+
- Fixed issue where `ps:wait` command hangs forever if workloads are suspended. [PR 198](https://github.com/shakacode/control-plane-flow/pull/198) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
- Added a timeout for `run` jobs (6 hours by default, but configurable through `runner_job_timeout` in `controlplane.yml`). [PR 194](https://github.com/shakacode/control-plane-flow/pull/194) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
|
27
|
+
- `run` command now overrides the `--image`, `--cpu`, and `--memory` for each job separately, which completely removes any race conditions when running simultaneous jobs with different overrides. [PR 182](https://github.com/shakacode/control-plane-flow/pull/182) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
28
|
+
- `run` jobs now use a CPU size of 1 (1 core) and a memory size of 2Gi (2 gibibytes) by default (configurable through `runner_job_default_cpu` and `runner_job_default_memory` in `controlplane.yml`). [PR 182](https://github.com/shakacode/control-plane-flow/pull/182) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
29
|
+
- `run` command now keeps ENV values synced between original and runner workloads. [PR 196](https://github.com/shakacode/control-plane-flow/pull/196) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
30
|
+
|
31
|
+
## [2.1.0] - 2024-05-27
|
32
|
+
|
33
|
+
### Fixed
|
34
|
+
|
19
35
|
- Fixed issue where release script was not running from the app image. [PR 183](https://github.com/shakacode/control-plane-flow/pull/183) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
20
36
|
- Fixed issue where deprecated options were not being warned. [PR 183](https://github.com/shakacode/control-plane-flow/pull/183) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
21
37
|
|
@@ -214,7 +230,8 @@ _Please add entries here for your pull requests that have not yet been released.
|
|
214
230
|
|
215
231
|
- Initial release
|
216
232
|
|
217
|
-
[Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v2.0
|
233
|
+
[Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v2.1.0...HEAD
|
234
|
+
[2.1.0]: https://github.com/shakacode/control-plane-flow/compare/v2.0.2...v2.1.0
|
218
235
|
[2.0.2]: https://github.com/shakacode/control-plane-flow/compare/v2.0.1...v2.0.2
|
219
236
|
[2.0.1]: https://github.com/shakacode/control-plane-flow/compare/v2.0.0...v2.0.1
|
220
237
|
[2.0.0]: https://github.com/shakacode/control-plane-flow/compare/v1.4.0...v2.0.0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cpl (2.
|
4
|
+
cpl (2.2.0)
|
5
5
|
debug (~> 1.7.1)
|
6
6
|
dotenv (~> 2.8.1)
|
7
7
|
jwt (~> 2.8.1)
|
@@ -52,7 +52,7 @@ GEM
|
|
52
52
|
rdoc (6.7.0)
|
53
53
|
psych (>= 4.0.0)
|
54
54
|
regexp_parser (2.9.0)
|
55
|
-
reline (0.5.
|
55
|
+
reline (0.5.8)
|
56
56
|
io-console (~> 0.5)
|
57
57
|
rexml (3.2.6)
|
58
58
|
rspec (3.12.0)
|
data/README.md
CHANGED
@@ -249,6 +249,18 @@ aliases:
|
|
249
249
|
# when running `cpl run`.
|
250
250
|
fix_terminal_size: true
|
251
251
|
|
252
|
+
# Sets a default CPU size for `cpl run` jobs (can be overridden per job through `--cpu`).
|
253
|
+
# If not specified, defaults to "1" (1 core).
|
254
|
+
runner_job_default_cpu: "2"
|
255
|
+
|
256
|
+
# Sets a default memory size for `cpl run` jobs (can be overridden per job through `--memory`).
|
257
|
+
# If not specified, defaults to "2Gi" (2 gibibytes).
|
258
|
+
runner_job_default_memory: "4Gi"
|
259
|
+
|
260
|
+
# Sets the maximum number of seconds that `cpl run` jobs can execute before being stopped.
|
261
|
+
# If not specified, defaults to 21600 (6 hours).
|
262
|
+
runner_job_timeout: 1000
|
263
|
+
|
252
264
|
# Apps with a deployed image created before this amount of days will be listed for deletion
|
253
265
|
# when running the command `cpl cleanup-stale-apps`.
|
254
266
|
stale_app_image_deployed_days: 5
|
data/docs/commands.md
CHANGED
@@ -371,12 +371,17 @@ cpl ps:swait -a $APP_NAME -w $WORKLOAD_NAME
|
|
371
371
|
- - log async fetching for non-interactive mode
|
372
372
|
- The Dockerfile entrypoint is used as the command by default, which assumes `exec "${@}"` to be present,
|
373
373
|
and the args ["bash", "-c", cmd_to_run] are passed
|
374
|
-
- The entrypoint can be
|
374
|
+
- The entrypoint can be overridden through `--entrypoint`, which must be a single command or a script path that exists in the container,
|
375
375
|
and the args ["bash", "-c", cmd_to_run] are passed,
|
376
376
|
unless the entrypoint is `bash`, in which case the args ["-c", cmd_to_run] are passed
|
377
377
|
- Providing `--entrypoint none` sets the entrypoint to `bash` by default
|
378
378
|
- If `fix_terminal_size` is `true` in the `.controlplane/controlplane.yml` file,
|
379
|
-
the remote terminal size will be fixed to match the local terminal size (may also be
|
379
|
+
the remote terminal size will be fixed to match the local terminal size (may also be overridden through `--terminal-size`)
|
380
|
+
- By default, all jobs use a CPU size of 1 (1 core) and a memory size of 2Gi (2 gibibytes)
|
381
|
+
(can be configured through `runner_job_default_cpu` and `runner_job_default_memory` in `controlplane.yml`,
|
382
|
+
and also overridden per job through `--cpu` and `--memory`)
|
383
|
+
- By default, the job is stopped if it takes longer than 6 hours to finish
|
384
|
+
(can be configured though `runner_job_timeout` in `controlplane.yml`)
|
380
385
|
|
381
386
|
```sh
|
382
387
|
# Opens shell (bash by default).
|
data/examples/controlplane.yml
CHANGED
@@ -84,6 +84,18 @@ aliases:
|
|
84
84
|
# when running `cpl run`.
|
85
85
|
fix_terminal_size: true
|
86
86
|
|
87
|
+
# Sets a default CPU size for `cpl run` jobs (can be overridden per job through `--cpu`).
|
88
|
+
# If not specified, defaults to "1" (1 core).
|
89
|
+
runner_job_default_cpu: "2"
|
90
|
+
|
91
|
+
# Sets a default memory size for `cpl run` jobs (can be overridden per job through `--memory`).
|
92
|
+
# If not specified, defaults to "2Gi" (2 gibibytes).
|
93
|
+
runner_job_default_memory: "4Gi"
|
94
|
+
|
95
|
+
# Sets the maximum number of seconds that `cpl run` jobs can execute before being stopped.
|
96
|
+
# If not specified, defaults to 21600 (6 hours).
|
97
|
+
runner_job_timeout: 1000
|
98
|
+
|
87
99
|
# Apps with a deployed image created before this amount of days will be listed for deletion
|
88
100
|
# when running the command `cpl cleanup-stale-apps`.
|
89
101
|
stale_app_image_deployed_days: 5
|
data/lib/command/ps_wait.rb
CHANGED
@@ -22,13 +22,17 @@ module Command
|
|
22
22
|
```
|
23
23
|
EX
|
24
24
|
|
25
|
-
def call
|
25
|
+
def call # rubocop:disable Metrics/MethodLength
|
26
26
|
@workloads = [config.options[:workload]] if config.options[:workload]
|
27
27
|
@workloads ||= config[:app_workloads] + config[:additional_workloads]
|
28
28
|
|
29
29
|
@workloads.reverse_each do |workload|
|
30
|
-
|
31
|
-
|
30
|
+
if cp.workload_suspended?(workload)
|
31
|
+
progress.puts("Workload '#{workload}' is suspended. Skipping...")
|
32
|
+
else
|
33
|
+
step("Waiting for workload '#{workload}' to be ready", retry_on_failure: true) do
|
34
|
+
cp.workload_deployments_ready?(workload, location: config.location, expected_status: true)
|
35
|
+
end
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
data/lib/command/run.rb
CHANGED
@@ -36,12 +36,17 @@ module Command
|
|
36
36
|
- - log async fetching for non-interactive mode
|
37
37
|
- The Dockerfile entrypoint is used as the command by default, which assumes `exec "${@}"` to be present,
|
38
38
|
and the args ["bash", "-c", cmd_to_run] are passed
|
39
|
-
- The entrypoint can be
|
39
|
+
- The entrypoint can be overridden through `--entrypoint`, which must be a single command or a script path that exists in the container,
|
40
40
|
and the args ["bash", "-c", cmd_to_run] are passed,
|
41
41
|
unless the entrypoint is `bash`, in which case the args ["-c", cmd_to_run] are passed
|
42
42
|
- Providing `--entrypoint none` sets the entrypoint to `bash` by default
|
43
43
|
- If `fix_terminal_size` is `true` in the `.controlplane/controlplane.yml` file,
|
44
|
-
the remote terminal size will be fixed to match the local terminal size (may also be
|
44
|
+
the remote terminal size will be fixed to match the local terminal size (may also be overridden through `--terminal-size`)
|
45
|
+
- By default, all jobs use a CPU size of 1 (1 core) and a memory size of 2Gi (2 gibibytes)
|
46
|
+
(can be configured through `runner_job_default_cpu` and `runner_job_default_memory` in `controlplane.yml`,
|
47
|
+
and also overridden per job through `--cpu` and `--memory`)
|
48
|
+
- By default, the job is stopped if it takes longer than 6 hours to finish
|
49
|
+
(can be configured though `runner_job_timeout` in `controlplane.yml`)
|
45
50
|
DESC
|
46
51
|
EXAMPLES = <<~EX
|
47
52
|
```sh
|
@@ -84,12 +89,17 @@ module Command
|
|
84
89
|
```
|
85
90
|
EX
|
86
91
|
|
92
|
+
DEFAULT_JOB_CPU = "1"
|
93
|
+
DEFAULT_JOB_MEMORY = "2Gi"
|
94
|
+
DEFAULT_JOB_TIMEOUT = 21_600 # 6 hours
|
95
|
+
DEFAULT_JOB_HISTORY_LIMIT = 10
|
87
96
|
MAGIC_END = "---cpl run command finished---"
|
88
97
|
|
89
98
|
attr_reader :interactive, :detached, :location, :original_workload, :runner_workload,
|
99
|
+
:default_image, :default_cpu, :default_memory, :job_timeout, :job_history_limit,
|
90
100
|
:container, :expected_deployed_version, :job, :replica, :command
|
91
101
|
|
92
|
-
def call # rubocop:disable Metrics/MethodLength
|
102
|
+
def call # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
93
103
|
@interactive = config.options[:interactive] || interactive_command?
|
94
104
|
@detached = config.options[:detached]
|
95
105
|
@log_method = config.options[:log_method]
|
@@ -97,6 +107,11 @@ module Command
|
|
97
107
|
@location = config.location
|
98
108
|
@original_workload = config.options[:workload] || config[:one_off_workload]
|
99
109
|
@runner_workload = "#{original_workload}-runner"
|
110
|
+
@default_image = "#{config.app}:#{Controlplane::NO_IMAGE_AVAILABLE}"
|
111
|
+
@default_cpu = config.current[:runner_job_default_cpu] || DEFAULT_JOB_CPU
|
112
|
+
@default_memory = config.current[:runner_job_default_memory] || DEFAULT_JOB_MEMORY
|
113
|
+
@job_timeout = config.current[:runner_job_timeout] || DEFAULT_JOB_TIMEOUT
|
114
|
+
@job_history_limit = DEFAULT_JOB_HISTORY_LIMIT
|
100
115
|
|
101
116
|
unless interactive
|
102
117
|
@internal_sigint = false
|
@@ -110,12 +125,10 @@ module Command
|
|
110
125
|
end
|
111
126
|
end
|
112
127
|
|
113
|
-
if cp.fetch_workload(runner_workload).nil?
|
114
|
-
|
115
|
-
wait_for_runner_workload_create
|
116
|
-
end
|
128
|
+
create_runner_workload if cp.fetch_workload(runner_workload).nil?
|
129
|
+
wait_for_runner_workload_deploy
|
117
130
|
update_runner_workload
|
118
|
-
wait_for_runner_workload_update
|
131
|
+
wait_for_runner_workload_update if expected_deployed_version
|
119
132
|
|
120
133
|
start_job
|
121
134
|
wait_for_replica_for_job
|
@@ -154,6 +167,11 @@ module Command
|
|
154
167
|
container_spec.delete("livenessProbe")
|
155
168
|
container_spec.delete("readinessProbe")
|
156
169
|
|
170
|
+
# Set image, CPU, and memory to default values
|
171
|
+
container_spec["image"] = default_image
|
172
|
+
container_spec["cpu"] = default_cpu
|
173
|
+
container_spec["memory"] = default_memory
|
174
|
+
|
157
175
|
# Ensure cron workload won't run per schedule
|
158
176
|
spec["defaultOptions"]["suspend"] = true
|
159
177
|
|
@@ -163,9 +181,14 @@ module Command
|
|
163
181
|
|
164
182
|
# Set cron job props
|
165
183
|
spec["type"] = "cron"
|
184
|
+
spec["job"] = {
|
185
|
+
# Next job set to run on January 1st, 2029
|
186
|
+
"schedule" => "0 0 1 1 1",
|
166
187
|
|
167
|
-
|
168
|
-
|
188
|
+
"restartPolicy" => "Never",
|
189
|
+
"activeDeadlineSeconds" => job_timeout,
|
190
|
+
"historyLimit" => job_history_limit
|
191
|
+
}
|
169
192
|
|
170
193
|
# Create runner workload
|
171
194
|
cp.apply_hash("kind" => "workload", "name" => runner_workload, "spec" => spec)
|
@@ -173,46 +196,60 @@ module Command
|
|
173
196
|
end
|
174
197
|
|
175
198
|
def update_runner_workload # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
176
|
-
|
177
|
-
|
178
|
-
should_update = false
|
199
|
+
should_update = false
|
200
|
+
spec = nil
|
179
201
|
|
202
|
+
step("Checking if runner workload '#{runner_workload}' needs to be updated") do # rubocop:disable Metrics/BlockLength
|
180
203
|
_, original_container_spec = base_workload_specs(original_workload)
|
181
204
|
spec, container_spec = base_workload_specs(runner_workload)
|
182
205
|
|
183
|
-
#
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
if container_spec["image"] !=
|
192
|
-
container_spec["image"] =
|
206
|
+
# Keep ENV synced between original and runner workloads
|
207
|
+
original_env_str = original_container_spec["env"]&.sort_by { |env| env["name"] }.to_s
|
208
|
+
env_str = container_spec["env"]&.sort_by { |env| env["name"] }.to_s
|
209
|
+
if original_env_str != env_str
|
210
|
+
container_spec["env"] = original_container_spec["env"]
|
211
|
+
should_update = true
|
212
|
+
end
|
213
|
+
|
214
|
+
if container_spec["image"] != default_image
|
215
|
+
container_spec["image"] = default_image
|
193
216
|
should_update = true
|
194
217
|
end
|
195
218
|
|
196
|
-
|
197
|
-
|
198
|
-
container_spec["cpu"] = config.options[:cpu]
|
219
|
+
if container_spec["cpu"] != default_cpu
|
220
|
+
container_spec["cpu"] = default_cpu
|
199
221
|
should_update = true
|
200
222
|
end
|
201
|
-
|
202
|
-
|
223
|
+
|
224
|
+
if container_spec["memory"] != default_memory
|
225
|
+
container_spec["memory"] = default_memory
|
203
226
|
should_update = true
|
204
227
|
end
|
205
228
|
|
206
|
-
|
229
|
+
if spec["job"]["activeDeadlineSeconds"] != job_timeout
|
230
|
+
spec["job"]["activeDeadlineSeconds"] = job_timeout
|
231
|
+
should_update = true
|
232
|
+
end
|
207
233
|
|
234
|
+
if spec["job"]["historyLimit"] != job_history_limit
|
235
|
+
spec["job"]["historyLimit"] = job_history_limit
|
236
|
+
should_update = true
|
237
|
+
end
|
238
|
+
|
239
|
+
true
|
240
|
+
end
|
241
|
+
|
242
|
+
return unless should_update
|
243
|
+
|
244
|
+
step("Updating runner workload '#{runner_workload}'") do
|
208
245
|
# Update runner workload
|
209
|
-
@expected_deployed_version
|
246
|
+
@expected_deployed_version = cp.cron_workload_deployed_version(runner_workload) + 1
|
210
247
|
cp.apply_hash("kind" => "workload", "name" => runner_workload, "spec" => spec)
|
211
248
|
end
|
212
249
|
end
|
213
250
|
|
214
|
-
def
|
215
|
-
step("Waiting for runner workload '#{runner_workload}' to be
|
251
|
+
def wait_for_runner_workload_deploy
|
252
|
+
step("Waiting for runner workload '#{runner_workload}' to be deployed", retry_on_failure: true) do
|
216
253
|
!cp.cron_workload_deployed_version(runner_workload).nil?
|
217
254
|
end
|
218
255
|
end
|
@@ -302,12 +339,14 @@ module Command
|
|
302
339
|
def base_workload_specs(workload)
|
303
340
|
spec = cp.fetch_workload!(workload).fetch("spec")
|
304
341
|
container_spec = spec["containers"].detect { _1["name"] == original_workload } || spec["containers"].first
|
305
|
-
@container = container_spec["name"]
|
306
342
|
|
307
343
|
[spec, container_spec]
|
308
344
|
end
|
309
345
|
|
310
346
|
def build_job_start_yaml # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
347
|
+
_, original_container_spec = base_workload_specs(original_workload)
|
348
|
+
@container = original_container_spec["name"]
|
349
|
+
|
311
350
|
job_start_hash = { "name" => container }
|
312
351
|
|
313
352
|
if config.options[:use_local_token]
|
@@ -335,6 +374,18 @@ module Command
|
|
335
374
|
job_start_hash["args"].push('eval "$CPL_RUNNER_SCRIPT"')
|
336
375
|
end
|
337
376
|
|
377
|
+
image = config.options[:image]
|
378
|
+
image_link = if image
|
379
|
+
image = cp.latest_image if image == "latest"
|
380
|
+
"/org/#{config.org}/image/#{image}"
|
381
|
+
else
|
382
|
+
original_container_spec["image"]
|
383
|
+
end
|
384
|
+
|
385
|
+
job_start_hash["image"] = image_link
|
386
|
+
job_start_hash["cpu"] = config.options[:cpu] if config.options[:cpu]
|
387
|
+
job_start_hash["memory"] = config.options[:memory] if config.options[:memory]
|
388
|
+
|
338
389
|
job_start_hash.to_yaml
|
339
390
|
end
|
340
391
|
|
@@ -434,6 +485,8 @@ module Command
|
|
434
485
|
end
|
435
486
|
|
436
487
|
def print_detached_commands
|
488
|
+
return unless replica
|
489
|
+
|
437
490
|
app_workload_replica_config = app_workload_replica_args.join(" ")
|
438
491
|
progress.puts(
|
439
492
|
"\n\n" \
|
@@ -451,7 +504,7 @@ module Command
|
|
451
504
|
Shell.debug("JOB STATUS", status)
|
452
505
|
|
453
506
|
case status
|
454
|
-
when "active"
|
507
|
+
when "active", "pending"
|
455
508
|
sleep 1
|
456
509
|
when "successful"
|
457
510
|
break ExitCode::SUCCESS
|
data/lib/core/controlplane.rb
CHANGED
@@ -256,6 +256,11 @@ class Controlplane # rubocop:disable Metrics/ClassLength
|
|
256
256
|
api.update_workload(org: org, gvc: gvc, workload: workload, data: data)
|
257
257
|
end
|
258
258
|
|
259
|
+
def workload_suspended?(workload)
|
260
|
+
details = fetch_workload!(workload)
|
261
|
+
details["spec"]["defaultOptions"]["suspend"]
|
262
|
+
end
|
263
|
+
|
259
264
|
def workload_force_redeployment(workload)
|
260
265
|
cmd = "cpln workload force-redeployment #{workload} #{gvc_org}"
|
261
266
|
perform!(cmd)
|
data/lib/cpl/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cpl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
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-
|
12
|
+
date: 2024-06-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: debug
|