cpl 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|