cpl 2.0.2 → 2.1.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/.gitignore +1 -0
- data/CHANGELOG.md +22 -1
- data/Gemfile.lock +2 -2
- data/README.md +12 -3
- data/docs/commands.md +30 -6
- data/docs/secrets-and-env-values.md +42 -0
- data/docs/tips.md +1 -40
- data/examples/controlplane.yml +12 -3
- data/lib/command/apply_template.rb +70 -80
- data/lib/command/base.rb +82 -71
- data/lib/command/build_image.rb +2 -2
- data/lib/command/cleanup_images.rb +1 -1
- data/lib/command/cleanup_stale_apps.rb +1 -1
- data/lib/command/copy_image_from_upstream.rb +3 -3
- data/lib/command/delete.rb +17 -5
- data/lib/command/deploy_image.rb +6 -21
- data/lib/command/doctor.rb +47 -0
- data/lib/command/latest_image.rb +1 -1
- data/lib/command/no_command.rb +1 -0
- data/lib/command/promote_app_from_upstream.rb +1 -1
- data/lib/command/run.rb +1 -1
- data/lib/command/setup_app.rb +80 -16
- data/lib/command/test.rb +1 -0
- data/lib/command/version.rb +1 -0
- data/lib/core/config.rb +40 -12
- data/lib/core/controlplane.rb +53 -0
- data/lib/core/controlplane_api.rb +13 -7
- data/lib/core/controlplane_api_direct.rb +1 -1
- data/lib/core/doctor_service.rb +104 -0
- data/lib/core/helpers.rb +10 -0
- data/lib/core/template_parser.rb +76 -0
- data/lib/cpl/version.rb +1 -1
- data/lib/cpl.rb +24 -6
- data/templates/app.yml +0 -5
- metadata +6 -4
- data/lib/core/controlplane_api_cli.rb +0 -10
- data/templates/secrets.yml +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 468f47cb0e1cf3cdb710b885949188c68f40fd74ad4236379a5a6c6fd55739c1
|
4
|
+
data.tar.gz: fc83d4ef5ee3ded08d52ca5f2df92e5ee261df6fcefd27f673452d0ba265a650
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dac1051680d2b3c69473636a9babd19b8799ea6e2eaadbb26582836641f7a73e843e4a26c32f41206edb0a6b21ab89b9b62cc08087360d75a562c3b6bb40188d
|
7
|
+
data.tar.gz: 52ca1f46ff0d459f450e1a1bd82b6efce780e9b6480ebbda955722eef4bea3a98d71cdaff076691b4cfe93e77c42285f358bfb4ba9adf857c961108302a4f5d6
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -14,6 +14,26 @@ 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 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
|
+
- 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
|
+
|
22
|
+
### Added
|
23
|
+
|
24
|
+
- 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).
|
25
|
+
- 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).
|
26
|
+
- Added `doctor` command to run validations. [PR 185](https://github.com/shakacode/control-plane-flow/pull/185) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
27
|
+
|
28
|
+
### Changed
|
29
|
+
|
30
|
+
- `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).
|
31
|
+
- `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).
|
32
|
+
- 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).
|
33
|
+
- 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).
|
34
|
+
|
35
|
+
## [2.0.2] - 2024-05-17
|
36
|
+
|
17
37
|
- 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
38
|
|
19
39
|
## [2.0.1] - 2024-05-15
|
@@ -194,7 +214,8 @@ _Please add entries here for your pull requests that have not yet been released.
|
|
194
214
|
|
195
215
|
- Initial release
|
196
216
|
|
197
|
-
[Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v2.0.
|
217
|
+
[Unreleased]: https://github.com/shakacode/control-plane-flow/compare/v2.0.2...HEAD
|
218
|
+
[2.0.2]: https://github.com/shakacode/control-plane-flow/compare/v2.0.1...v2.0.2
|
198
219
|
[2.0.1]: https://github.com/shakacode/control-plane-flow/compare/v2.0.0...v2.0.1
|
199
220
|
[2.0.0]: https://github.com/shakacode/control-plane-flow/compare/v1.4.0...v2.0.0
|
200
221
|
[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
|
4
|
+
cpl (2.1.0)
|
5
5
|
debug (~> 1.7.1)
|
6
6
|
dotenv (~> 2.8.1)
|
7
7
|
jwt (~> 2.8.1)
|
@@ -49,7 +49,7 @@ GEM
|
|
49
49
|
racc (1.7.3)
|
50
50
|
rainbow (3.1.1)
|
51
51
|
rake (13.2.1)
|
52
|
-
rdoc (6.
|
52
|
+
rdoc (6.7.0)
|
53
53
|
psych (>= 4.0.0)
|
54
54
|
regexp_parser (2.9.0)
|
55
55
|
reline (0.5.7)
|
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`,
|
@@ -273,6 +273,15 @@ apps:
|
|
273
273
|
# e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
|
274
274
|
match_if_app_name_starts_with: true
|
275
275
|
|
276
|
+
# Hooks can be either a script path that exists in the app image or a command.
|
277
|
+
# They're run in the context of `cpl run` with the latest image.
|
278
|
+
hooks:
|
279
|
+
# Used by the command `cpl setup-app` to run a hook after creating the app.
|
280
|
+
post_creation: bundle exec rake db:prepare
|
281
|
+
|
282
|
+
# Used by the command `cpl delete` to run a hook before deleting the app.
|
283
|
+
pre_deletion: bundle exec rake db:drop
|
284
|
+
|
276
285
|
my-app-production:
|
277
286
|
<<: *common
|
278
287
|
|
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
|
-
-
|
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
|
-
-
|
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
|
-
-
|
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
|
@@ -407,9 +425,15 @@ cpl run -a $APP_NAME --entrypoint /app/alternative-entrypoint.sh -- rails db:mig
|
|
407
425
|
|
408
426
|
- Creates an app and all its workloads
|
409
427
|
- 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
|
-
-
|
412
|
-
-
|
428
|
+
- 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)
|
429
|
+
- Configures app to have org-level secrets with default name "{APP_PREFIX}-secrets"
|
430
|
+
using org-level policy with default name "{APP_PREFIX}-secrets-policy" (names can be customized, see docs)
|
431
|
+
- Creates identity for secrets if it does not exist
|
432
|
+
- Use `--skip-secrets-setup` to prevent the automatic setup of secrets,
|
433
|
+
or set it through `skip_secrets_setup` in the `.controlplane/controlplane.yml` file
|
434
|
+
- Runs a post-creation hook after the app is created if `hooks.post_creation` is specified in the `.controlplane/controlplane.yml` file
|
435
|
+
- If the hook exits with a non-zero code, the command will stop executing and also exit with a non-zero code
|
436
|
+
- Use `--skip-post-creation-hook` to skip the hook if specified in `controlplane.yml`
|
413
437
|
|
414
438
|
```sh
|
415
439
|
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](
|
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
|
data/examples/controlplane.yml
CHANGED
@@ -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`,
|
@@ -108,6 +108,15 @@ apps:
|
|
108
108
|
# e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
|
109
109
|
match_if_app_name_starts_with: true
|
110
110
|
|
111
|
+
# Hooks can be either a script path that exists in the app image or a command.
|
112
|
+
# They're run in the context of `cpl run` with the latest image.
|
113
|
+
hooks:
|
114
|
+
# Used by the command `cpl setup-app` to run a hook after creating the app.
|
115
|
+
post_creation: bundle exec rake db:prepare
|
116
|
+
|
117
|
+
# Used by the command `cpl delete` to run a hook before deleting the app.
|
118
|
+
pre_deletion: bundle exec rake db:drop
|
119
|
+
|
111
120
|
my-app-production:
|
112
121
|
<<: *common
|
113
122
|
|
@@ -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
|
-
|
51
|
-
|
52
|
-
pending_templates
|
53
|
-
|
54
|
-
|
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
|
91
|
-
|
92
|
-
|
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 =
|
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 |
|
101
|
-
" - #{
|
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 '#{
|
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
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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
|
-
|
137
|
+
progress.puts if @asked_for_confirmation
|
138
|
+
|
139
|
+
pending_templates
|
140
|
+
end
|
151
141
|
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
160
|
-
|
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
|
154
|
+
def build_app_identity_hash
|
164
155
|
{
|
165
|
-
"
|
166
|
-
"
|
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
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|