cpl 2.0.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87e32bc116e1b72a8282d38542a4ff8ba39240b4038e5cd5ad61bb7fda27a492
4
- data.tar.gz: 496bc3b6fc6c49f6865a430c91d12e98400c6af3e9eb97cac24090b575365918
3
+ metadata.gz: 27661f3a2e2aff2f7018e2cb0e77835ee4de88a8ee0268ec549cafa9d02dfbaa
4
+ data.tar.gz: 001a114b051c3501b5449eb6d3e4c9f7dea3fa608c6e4595e2129c3bcad8f855
5
5
  SHA512:
6
- metadata.gz: 6ac8eec9af37340bb5c2ac4b635daf6ab1b60c77893ecd412224879ae700c1569b0ac76675f520b245f4021d1d7476aafb95d5d067b4e5efaabedee1a8068176
7
- data.tar.gz: 9d67284e4db41824b6492dd9a9aa6db37ea49261ac965dadc6efad5e0d4a4f9cc1aa383aac3964bd16ee5b879a76ee63dafa5f895a0e451a033bf35efce591b3
6
+ metadata.gz: 38dfd9ca9aa2d28dc7df577677e5732f37740448beb857269ff156da7a8ff2f8627872c958b63e9d1d308ce091df1376e44c09aff96bc82f128edb887e1aba94
7
+ data.tar.gz: 14c73bf485166dd5be51ff276b6cef8aa3152bb0482fd92b6752e47575cd43ab0bd620ba1c49de619863cff955b628477eb32188a8f76393423c50b1a81e5b07
data/.gitignore CHANGED
@@ -15,3 +15,4 @@
15
15
  .rspec_status
16
16
 
17
17
  /spec.log
18
+ /spec/dummy/.controlplane/controlplane*-tmp-*.yml
data/CHANGELOG.md CHANGED
@@ -14,6 +14,42 @@ 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 `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
+
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).
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).
37
+
38
+ ### Added
39
+
40
+ - Added post-creation hook to `setup-app` command (configurable through `hooks.post_creation` in `controlplane.yml`). [PR 183](https://github.com/shakacode/control-plane-flow/pull/183) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
41
+ - Added pre-deletion hook to `delete` command (configurable through `hooks.pre_deletion` in `controlplane.yml`). [PR 183](https://github.com/shakacode/control-plane-flow/pull/183) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
42
+ - Added `doctor` command to run validations. [PR 185](https://github.com/shakacode/control-plane-flow/pull/185) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
43
+
44
+ ### Changed
45
+
46
+ - `cpl` now sets `CPLN_SKIP_UPDATE_CHECK` to `true` for all internal `cpln` calls, which disables the version check and prevents cluttering the logs. [PR 180](https://github.com/shakacode/control-plane-flow/pull/180) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
47
+ - `setup-app` command now automatically creates a secret, policy, and identity for the app if they do not exist. The `--skip-secrets-setup` option prevents this behavior. [PR 181](https://github.com/shakacode/control-plane-flow/pull/181) by [Rafael Gomes](https://github.com/rafaelgomesxyz). [PR 190](https://github.com/shakacode/control-plane-flow/pull/190) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
48
+ - 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).
49
+ - 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).
50
+
51
+ ## [2.0.2] - 2024-05-17
52
+
17
53
  - 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).
18
54
 
19
55
  ## [2.0.1] - 2024-05-15
@@ -194,7 +230,9 @@ _Please add entries here for your pull requests that have not yet been released.
194
230
 
195
231
  - Initial release
196
232
 
197
- [Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v2.0.1...HEAD
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
235
+ [2.0.2]: https://github.com/shakacode/control-plane-flow/compare/v2.0.1...v2.0.2
198
236
  [2.0.1]: https://github.com/shakacode/control-plane-flow/compare/v2.0.0...v2.0.1
199
237
  [2.0.0]: https://github.com/shakacode/control-plane-flow/compare/v1.4.0...v2.0.0
200
238
  [1.4.0]: https://github.com/shakacode/control-plane-flow/compare/v1.3.0...v1.4.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cpl (2.0.2)
4
+ cpl (2.2.0)
5
5
  debug (~> 1.7.1)
6
6
  dotenv (~> 2.8.1)
7
7
  jwt (~> 2.8.1)
@@ -49,10 +49,10 @@ GEM
49
49
  racc (1.7.3)
50
50
  rainbow (3.1.1)
51
51
  rake (13.2.1)
52
- rdoc (6.6.3.1)
52
+ rdoc (6.7.0)
53
53
  psych (>= 4.0.0)
54
54
  regexp_parser (2.9.0)
55
- reline (0.5.7)
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
@@ -196,9 +196,6 @@ aliases:
196
196
  # 2. Each file can contain many objects, such as in the case of templates that create a resource, like `postgres`.
197
197
  # 3. While the naming often corresponds to a workload or other object name, the naming is arbitrary.
198
198
  # Naming does not need to match anything other than the file name without the `.yml` extension.
199
- #
200
- # If you're going to use secrets, you need to apply the `secrets.yml` template separately (one-time setup):
201
- # `cpl apply-template secrets -a my-app`
202
199
  setup_app_templates:
203
200
  - app
204
201
  - redis
@@ -207,6 +204,9 @@ aliases:
207
204
  - rails
208
205
  - sidekiq
209
206
 
207
+ # Skips secrets setup when running `cpl setup-app`.
208
+ skip_secrets_setup: true
209
+
210
210
  # Only needed if using a custom secrets name.
211
211
  # The default is '{APP_PREFIX}-secrets'. For example:
212
212
  # - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
@@ -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
@@ -273,6 +285,15 @@ apps:
273
285
  # e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
274
286
  match_if_app_name_starts_with: true
275
287
 
288
+ # Hooks can be either a script path that exists in the app image or a command.
289
+ # They're run in the context of `cpl run` with the latest image.
290
+ hooks:
291
+ # Used by the command `cpl setup-app` to run a hook after creating the app.
292
+ post_creation: bundle exec rake db:prepare
293
+
294
+ # Used by the command `cpl delete` to run a hook before deleting the app.
295
+ pre_deletion: bundle exec rake db:drop
296
+
276
297
  my-app-production:
277
298
  <<: *common
278
299
 
data/docs/commands.md CHANGED
@@ -109,6 +109,9 @@ cpl copy-image-from-upstream -a $APP_NAME --upstream-token $UPSTREAM_TOKEN --ima
109
109
  - Deletes the whole app (GVC with all workloads, all volumesets and all images) or a specific workload
110
110
  - Also unbinds the app from the secrets policy, as long as both the identity and the policy exist (and are bound)
111
111
  - Will ask for explicit user confirmation
112
+ - Runs a pre-deletion hook before the app is deleted if `hooks.pre_deletion` is specified in the `.controlplane/controlplane.yml` file
113
+ - If the hook exits with a non-zero code, the command will stop executing and also exit with a non-zero code
114
+ - Use `--skip-pre-deletion-hook` to skip the hook if specified in `controlplane.yml`
112
115
 
113
116
  ```sh
114
117
  # Deletes the whole app (GVC with all workloads, all volumesets and all images).
@@ -121,14 +124,29 @@ cpl delete -a $APP_NAME -w $WORKLOAD_NAME
121
124
  ### `deploy-image`
122
125
 
123
126
  - Deploys the latest image to app workloads
124
- - Optionally runs a release script before deploying if specified through `release_script` in the `.controlplane/controlplane.yml` file and `--run-release-phase` is provided
127
+ - Runs a release script before deploying if `release_script` is specified in the `.controlplane/controlplane.yml` file and `--run-release-phase` is provided
125
128
  - The release script is run in the context of `cpl run` with the latest image
126
- - The deploy will fail if the release script exits with a non-zero code or doesn't exist
129
+ - If the release script exits with a non-zero code, the command will stop executing and also exit with a non-zero code
127
130
 
128
131
  ```sh
129
132
  cpl deploy-image -a $APP_NAME
130
133
  ```
131
134
 
135
+ ### `doctor`
136
+
137
+ - Runs validations
138
+
139
+ ```sh
140
+ # Runs all validations that don't require additional options by default.
141
+ cpl doctor
142
+
143
+ # Runs config validation.
144
+ cpl doctor --validations config
145
+
146
+ # Runs templates validation (requires app).
147
+ cpl doctor --validations templates -a $APP_NAME
148
+ ```
149
+
132
150
  ### `env`
133
151
 
134
152
  - Displays app-specific environment variables
@@ -276,7 +294,7 @@ cpl open-console -a $APP_NAME
276
294
  - Runs `cpl copy-image-from-upstream` to copy the latest image from upstream
277
295
  - Runs `cpl deploy-image` to deploy the image
278
296
  - If `.controlplane/controlplane.yml` includes the `release_script`, `cpl deploy-image` will use the `--run-release-phase` option
279
- - The deploy will fail if the release script exits with a non-zero code
297
+ - If the release script exits with a non-zero code, the command will stop executing and also exit with a non-zero code
280
298
 
281
299
  ```sh
282
300
  cpl promote-app-from-upstream -a $APP_NAME -t $UPSTREAM_TOKEN
@@ -353,12 +371,17 @@ cpl ps:swait -a $APP_NAME -w $WORKLOAD_NAME
353
371
  - - log async fetching for non-interactive mode
354
372
  - The Dockerfile entrypoint is used as the command by default, which assumes `exec "${@}"` to be present,
355
373
  and the args ["bash", "-c", cmd_to_run] are passed
356
- - The entrypoint can be overriden through `--entrypoint`, which must be a single command or a script path that exists in the container,
374
+ - The entrypoint can be overridden through `--entrypoint`, which must be a single command or a script path that exists in the container,
357
375
  and the args ["bash", "-c", cmd_to_run] are passed,
358
376
  unless the entrypoint is `bash`, in which case the args ["-c", cmd_to_run] are passed
359
377
  - Providing `--entrypoint none` sets the entrypoint to `bash` by default
360
378
  - If `fix_terminal_size` is `true` in the `.controlplane/controlplane.yml` file,
361
- the remote terminal size will be fixed to match the local terminal size (may also be overriden through `--terminal-size`)
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`)
362
385
 
363
386
  ```sh
364
387
  # Opens shell (bash by default).
@@ -407,9 +430,15 @@ cpl run -a $APP_NAME --entrypoint /app/alternative-entrypoint.sh -- rails db:mig
407
430
 
408
431
  - Creates an app and all its workloads
409
432
  - Specify the templates for the app and workloads through `setup_app_templates` in the `.controlplane/controlplane.yml` file
410
- - This should only be used for temporary apps like review apps, never for persistent apps like production (to update workloads for those, use 'cpl apply-template' instead)
411
- - Automatically binds the app to the secrets policy, as long as both the identity and the policy exist
412
- - Use `--skip-secret-access-binding` to prevent the automatic bind
433
+ - This should only be used for temporary apps like review apps, never for persistent apps like production or staging (to update workloads for those, use 'cpl apply-template' instead)
434
+ - Configures app to have org-level secrets with default name "{APP_PREFIX}-secrets"
435
+ using org-level policy with default name "{APP_PREFIX}-secrets-policy" (names can be customized, see docs)
436
+ - Creates identity for secrets if it does not exist
437
+ - Use `--skip-secrets-setup` to prevent the automatic setup of secrets,
438
+ or set it through `skip_secrets_setup` in the `.controlplane/controlplane.yml` file
439
+ - Runs a post-creation hook after the app is created if `hooks.post_creation` is specified in the `.controlplane/controlplane.yml` file
440
+ - If the hook exits with a non-zero code, the command will stop executing and also exit with a non-zero code
441
+ - Use `--skip-post-creation-hook` to skip the hook if specified in `controlplane.yml`
413
442
 
414
443
  ```sh
415
444
  cpl setup-app -a $APP_NAME
@@ -0,0 +1,42 @@
1
+ # Secrets and ENV Values
2
+
3
+ You can store ENV values used by a container (within a workload) within Control Plane at the following levels:
4
+
5
+ 1. Workload Container
6
+ 2. GVC
7
+
8
+ For your "review apps," it is convenient to have simple ENVs stored in plain text in your source code. You will want to
9
+ keep some ENVs, like the Rails' `SECRET_KEY_BASE`, out of your source code. For staging and production apps, you will
10
+ set these values directly at the GVC or workload levels, so none of these ENV values are committed to the source code.
11
+
12
+ For storing ENVs in the source code, we can use a level of indirection so that you can store an ENV value in your source
13
+ code like `cpln://secret/my-app-review-env-secrets.SECRET_KEY_BASE` and then have the secret value stored at the org
14
+ level, which applies to your GVCs mapped to that org.
15
+
16
+ For setting up secrets, you'll need:
17
+
18
+ - **Org-level Secret:** This is where the values will be stored.
19
+ - **GVC Identity:** An identity that must be associated with each workload that requires access to the secret.
20
+ - **Org-level Policy:** A policy that binds the identity to the secret, granting the necessary permissions for the workload to access the secret.
21
+
22
+ You can do this during the initial app setup, like this:
23
+
24
+ 1. Add the template for `app` to `.controlplane/templates`
25
+ 2. Ensure that the `app` template is listed in `setup_app_templates` for the app in `.controlplane/controlplane.yml`
26
+ 3. Run `cpl setup-app -a $APP_NAME`
27
+ 4. The secrets, secrets policy and identity will be automatically created, along with the proper binding
28
+ 5. In the Control Plane console, upper left "Manage Org" menu, click on "Secrets"
29
+ 6. Find the created secret (it will be in the `$APP_PREFIX-secrets` format) and add the secret env vars there
30
+ 7. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/$APP_PREFIX-secrets.SOME_VAR`)
31
+
32
+ Here are the manual steps for reference. We recommend that you follow the steps above:
33
+
34
+ 1. In the upper left of the Control Plane console, "Manage Org" menu, click on "Secrets"
35
+ 2. Create a secret with `Secret Type: Dictionary` (e.g., `my-secrets`) and add the secret env vars there
36
+ 3. In the upper left "Manage GVC" menu, click on "Identities"
37
+ 4. Create an identity (e.g., `my-identity`)
38
+ 5. Navigate to the workload that you want to associate with the identity created
39
+ 6. Click "Identity" on the left menu and select the identity created
40
+ 7. In the lower left "Access Control" menu, click on "Policies"
41
+ 8. Create a policy with `Target Kind: Secret` and add a binding with the `reveal` permission for the identity created
42
+ 9. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/my-secrets.SOME_VAR`)
data/docs/tips.md CHANGED
@@ -3,7 +3,7 @@
3
3
  1. [GVCs vs. Orgs](#gvcs-vs-orgs)
4
4
  2. [RAM](#ram)
5
5
  3. [Remote IP](#remote-ip)
6
- 4. [ENV Values](#env-values)
6
+ 4. [Secrets and ENV Values](/docs/secrets-and-env-values.md)
7
7
  5. [CI](#ci)
8
8
  6. [Memcached](#memcached)
9
9
  7. [Sidekiq](#sidekiq)
@@ -70,45 +70,6 @@ pick those up and automatically populate `request.remote_ip`.
70
70
 
71
71
  So `REMOTE_ADDR` should not be used directly, only `request.remote_ip`.
72
72
 
73
- ## ENV Values
74
-
75
- You can store ENV values used by a container (within a workload) within Control Plane at the following levels:
76
-
77
- 1. Workload Container
78
- 2. GVC
79
-
80
- For your "review apps," it is convenient to have simple ENVs stored in plain text in your source code. You will want to
81
- keep some ENVs, like the Rails' `SECRET_KEY_BASE`, out of your source code. For staging and production apps, you will
82
- set these values directly at the GVC or workload levels, so none of these ENV values are committed to the source code.
83
-
84
- For storing ENVs in the source code, we can use a level of indirection so that you can store an ENV value in your source
85
- code like `cpln://secret/my-app-review-env-secrets.SECRET_KEY_BASE` and then have the secret value stored at the org
86
- level, which applies to your GVCs mapped to that org.
87
-
88
- You can do this during the initial app setup, like this:
89
-
90
- 1. Add the templates for `app` and `secrets` to `.controlplane/templates`
91
- 2. Ensure that the `app` template includes the `identity`
92
- 3. Ensure that the `app` template is listed in `setup_app_templates` for the app in `.controlplane/controlplane.yml`
93
- 4. Run `cpl apply-template secrets -a $APP_NAME` (one-time setup)
94
- 5. Run `cpl setup-app -a $APP_NAME`
95
- 6. The secrets, secrets policy and identity will be automatically created, along with the proper binding
96
- 7. In the Control Plane console, upper left "Manage Org" menu, click on "Secrets"
97
- 8. Find the created secret (it will be in the `$APP_PREFIX-secrets` format) and add the secret env vars there
98
- 9. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/$APP_PREFIX-secrets.SOME_VAR`)
99
-
100
- Here are the manual steps for reference. We recommend that you follow the steps above:
101
-
102
- 1. In the upper left of the Control Plane console, "Manage Org" menu, click on "Secrets"
103
- 2. Create a secret with `Secret Type: Dictionary` (e.g., `my-secrets`) and add the secret env vars there
104
- 3. In the upper left "Manage GVC" menu, click on "Identities"
105
- 4. Create an identity (e.g., `my-identity`)
106
- 5. Navigate to the workload that you want to associate with the identity created
107
- 6. Click "Identity" on the left menu and select the identity created
108
- 7. In the lower left "Access Control" menu, click on "Policies"
109
- 8. Create a policy with `Target Kind: Secret` and add a binding with the `reveal` permission for the identity created
110
- 9. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/my-secrets.SOME_VAR`)
111
-
112
73
  ## CI
113
74
 
114
75
  **Note:** Docker builds much slower on Apple Silicon, so try configuring CI to build the images when using Apple
@@ -31,9 +31,6 @@ aliases:
31
31
  # 2. Each file can contain many objects, such as in the case of templates that create a resource, like `postgres`.
32
32
  # 3. While the naming often corresponds to a workload or other object name, the naming is arbitrary.
33
33
  # Naming does not need to match anything other than the file name without the `.yml` extension.
34
- #
35
- # If you're going to use secrets, you need to apply the `secrets.yml` template separately (one-time setup):
36
- # `cpl apply-template secrets -a my-app`
37
34
  setup_app_templates:
38
35
  - app
39
36
  - redis
@@ -42,6 +39,9 @@ aliases:
42
39
  - rails
43
40
  - sidekiq
44
41
 
42
+ # Uncomment next line to skips secrets setup when running `cpl setup-app`.
43
+ # skip_secrets_setup: true
44
+
45
45
  # Only needed if using a custom secrets name.
46
46
  # The default is '{APP_PREFIX}-secrets'. For example:
47
47
  # - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
@@ -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
@@ -108,6 +120,15 @@ apps:
108
120
  # e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
109
121
  match_if_app_name_starts_with: true
110
122
 
123
+ # Hooks can be either a script path that exists in the app image or a command.
124
+ # They're run in the context of `cpl run` with the latest image.
125
+ hooks:
126
+ # Used by the command `cpl setup-app` to run a hook after creating the app.
127
+ post_creation: bundle exec rake db:prepare
128
+
129
+ # Used by the command `cpl delete` to run a hook before deleting the app.
130
+ pre_deletion: bundle exec rake db:drop
131
+
111
132
  my-app-production:
112
133
  <<: *common
113
134
 
@@ -8,7 +8,8 @@ module Command
8
8
  OPTIONS = [
9
9
  app_option(required: true),
10
10
  location_option,
11
- skip_confirm_option
11
+ skip_confirm_option,
12
+ add_app_identity_option
12
13
  ].freeze
13
14
  DESCRIPTION = "Applies application-specific configs from templates"
14
15
  LONG_DESCRIPTION = <<~DESC
@@ -39,45 +40,27 @@ module Command
39
40
  cpl apply-template app postgres redis rails -a $APP_NAME
40
41
  ```
41
42
  EX
43
+ VALIDATIONS = %w[config templates].freeze
44
+
45
+ def call # rubocop:disable Metrics/MethodLength
46
+ @template_parser = TemplateParser.new(config)
47
+ @names_to_filenames = config.args.to_h do |name|
48
+ [name, @template_parser.template_filename(name)]
49
+ end
42
50
 
43
- def call # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
44
51
  ensure_templates!
45
52
 
46
53
  @created_items = []
47
54
  @failed_templates = []
48
55
  @skipped_templates = []
49
56
 
50
- @asked_for_confirmation = false
51
-
52
- pending_templates = templates.select do |template|
53
- if template == "app"
54
- confirm_app(template)
55
- else
56
- confirm_workload(template)
57
- end
58
- end
59
-
60
- progress.puts if @asked_for_confirmation
61
-
62
- @deprecated_variables = []
63
-
64
- pending_templates.each do |template, filename|
65
- step("Applying template '#{template}'", abort_on_error: false) do
66
- items = apply_template(filename)
67
- unless items
68
- report_failure(template)
69
- next false
70
- end
71
-
72
- items.each do |item|
73
- report_success(item)
74
- end
75
- true
76
- end
57
+ templates = @template_parser.parse(@names_to_filenames.values)
58
+ pending_templates = confirm_templates(templates)
59
+ add_app_identity_template(pending_templates) if config.options[:add_app_identity]
60
+ pending_templates.each do |template|
61
+ apply_template(template)
77
62
  end
78
63
 
79
- warn_deprecated_variables
80
-
81
64
  print_created_items
82
65
  print_failed_templates
83
66
  print_skipped_templates
@@ -87,18 +70,21 @@ module Command
87
70
 
88
71
  private
89
72
 
90
- def templates
91
- @templates ||= config.args.to_h do |template|
92
- [template, "#{config.app_cpln_dir}/templates/#{template}.yml"]
73
+ def template_kind(template)
74
+ case template["kind"]
75
+ when "gvc"
76
+ "app"
77
+ else
78
+ template["kind"]
93
79
  end
94
80
  end
95
81
 
96
82
  def ensure_templates!
97
- missing_templates = templates.reject { |_template, filename| File.exist?(filename) }.to_h
83
+ missing_templates = @names_to_filenames.reject { |_, filename| File.exist?(filename) }
98
84
  return if missing_templates.empty?
99
85
 
100
- missing_templates_str = missing_templates.map do |template, filename|
101
- " - #{template} (#{filename})"
86
+ missing_templates_str = missing_templates.map do |name, filename|
87
+ " - #{name} (#{filename})"
102
88
  end.join("\n")
103
89
  progress.puts("#{Shell.color('Missing templates:', :red)}\n#{missing_templates_str}\n\n")
104
90
 
@@ -113,10 +99,10 @@ module Command
113
99
  end
114
100
 
115
101
  def confirm_app(template)
116
- app = cp.fetch_gvc
102
+ app = cp.fetch_gvc(template["name"])
117
103
  return true unless app
118
104
 
119
- confirmed = confirm_apply("App '#{config.app}' already exists, do you want to re-create it?")
105
+ confirmed = confirm_apply("App '#{template['name']}' already exists, do you want to re-create it?")
120
106
  return true if confirmed
121
107
 
122
108
  report_skipped(template)
@@ -124,63 +110,67 @@ module Command
124
110
  end
125
111
 
126
112
  def confirm_workload(template)
127
- workload = cp.fetch_workload(template)
113
+ workload = cp.fetch_workload(template["name"])
128
114
  return true unless workload
129
115
 
130
- confirmed = confirm_apply("Workload '#{template}' already exists, do you want to re-create it?")
116
+ confirmed = confirm_apply("Workload '#{template['name']}' already exists, do you want to re-create it?")
131
117
  return true if confirmed
132
118
 
133
119
  report_skipped(template)
134
120
  false
135
121
  end
136
122
 
137
- def apply_template(filename) # rubocop:disable Metrics/MethodLength
138
- data = File.read(filename)
139
- .gsub("{{APP_ORG}}", config.org)
140
- .gsub("{{APP_NAME}}", config.app)
141
- .gsub("{{APP_LOCATION}}", config.location)
142
- .gsub("{{APP_LOCATION_LINK}}", app_location_link)
143
- .gsub("{{APP_IMAGE}}", latest_image)
144
- .gsub("{{APP_IMAGE_LINK}}", app_image_link)
145
- .gsub("{{APP_IDENTITY}}", app_identity)
146
- .gsub("{{APP_IDENTITY_LINK}}", app_identity_link)
147
- .gsub("{{APP_SECRETS}}", app_secrets)
148
- .gsub("{{APP_SECRETS_POLICY}}", app_secrets_policy)
123
+ def confirm_templates(templates) # rubocop:disable Metrics/MethodLength
124
+ @asked_for_confirmation = false
125
+
126
+ pending_templates = templates.select do |template|
127
+ case template["kind"]
128
+ when "gvc"
129
+ confirm_app(template)
130
+ when "workload"
131
+ confirm_workload(template)
132
+ else
133
+ true
134
+ end
135
+ end
149
136
 
150
- find_deprecated_variables(data)
137
+ progress.puts if @asked_for_confirmation
138
+
139
+ pending_templates
140
+ end
151
141
 
152
- # Kept for backwards compatibility
153
- data = data
154
- .gsub("APP_ORG", config.org)
155
- .gsub("APP_GVC", config.app)
156
- .gsub("APP_LOCATION", config.location)
157
- .gsub("APP_IMAGE", latest_image)
142
+ def add_app_identity_template(templates)
143
+ app_template_index = templates.index { |template| template["name"] == config.app }
144
+ app_identity_template_index = templates.index { |template| template["name"] == config.identity }
158
145
 
159
- # Don't read in YAML.safe_load as that doesn't handle multiple documents
160
- cp.apply_template(data)
146
+ return unless app_template_index && app_identity_template_index.nil?
147
+
148
+ # Adding the identity template right after the app template is important since:
149
+ # a) we can't create the identity at the beginning because the app doesn't exist yet
150
+ # b) we also can't create it at the end because any workload templates associated with it will fail to apply
151
+ templates.insert(app_template_index + 1, build_app_identity_hash)
161
152
  end
162
153
 
163
- def new_variables
154
+ def build_app_identity_hash
164
155
  {
165
- "APP_ORG" => "{{APP_ORG}}",
166
- "APP_GVC" => "{{APP_NAME}}",
167
- "APP_LOCATION" => "{{APP_LOCATION}}",
168
- "APP_IMAGE" => "{{APP_IMAGE}}"
156
+ "kind" => "identity",
157
+ "name" => config.identity
169
158
  }
170
159
  end
171
160
 
172
- def find_deprecated_variables(data)
173
- @deprecated_variables.push(*new_variables.keys.select { |old_key| data.include?(old_key) })
174
- @deprecated_variables = @deprecated_variables.uniq.sort
175
- end
176
-
177
- def warn_deprecated_variables
178
- return unless @deprecated_variables.any?
161
+ def apply_template(template) # rubocop:disable Metrics/MethodLength
162
+ step("Applying template for #{template_kind(template)} '#{template['name']}'", abort_on_error: false) do
163
+ items = cp.apply_hash(template)
164
+ unless items
165
+ report_failure(template)
166
+ next false
167
+ end
179
168
 
180
- message = "Please replace these variables in the templates, " \
181
- "as support for them will be removed in a future major version bump:"
182
- deprecated = @deprecated_variables.map { |old_key| " - #{old_key} -> #{new_variables[old_key]}" }.join("\n")
183
- progress.puts("\n#{Shell.color("DEPRECATED: #{message}", :yellow)}\n#{deprecated}")
169
+ items.each do |item|
170
+ report_success(item)
171
+ end
172
+ true
173
+ end
184
174
  end
185
175
 
186
176
  def report_success(item)
@@ -205,14 +195,14 @@ module Command
205
195
  def print_failed_templates
206
196
  return unless @failed_templates.any?
207
197
 
208
- failed = @failed_templates.map { |template| " - #{template}" }.join("\n")
198
+ failed = @failed_templates.map { |template| " - [#{template_kind(template)}] #{template['name']}" }.join("\n")
209
199
  progress.puts("\n#{Shell.color('Failed to apply templates:', :red)}\n#{failed}")
210
200
  end
211
201
 
212
202
  def print_skipped_templates
213
203
  return unless @skipped_templates.any?
214
204
 
215
- skipped = @skipped_templates.map { |template| " - #{template}" }.join("\n")
205
+ skipped = @skipped_templates.map { |template| " - [#{template_kind(template)}] #{template['name']}" }.join("\n")
216
206
  progress.puts("\n#{Shell.color('Skipped templates (already exist):', :blue)}\n#{skipped}")
217
207
  end
218
208
  end