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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87e32bc116e1b72a8282d38542a4ff8ba39240b4038e5cd5ad61bb7fda27a492
4
- data.tar.gz: 496bc3b6fc6c49f6865a430c91d12e98400c6af3e9eb97cac24090b575365918
3
+ metadata.gz: 468f47cb0e1cf3cdb710b885949188c68f40fd74ad4236379a5a6c6fd55739c1
4
+ data.tar.gz: fc83d4ef5ee3ded08d52ca5f2df92e5ee261df6fcefd27f673452d0ba265a650
5
5
  SHA512:
6
- metadata.gz: 6ac8eec9af37340bb5c2ac4b635daf6ab1b60c77893ecd412224879ae700c1569b0ac76675f520b245f4021d1d7476aafb95d5d067b4e5efaabedee1a8068176
7
- data.tar.gz: 9d67284e4db41824b6492dd9a9aa6db37ea49261ac965dadc6efad5e0d4a4f9cc1aa383aac3964bd16ee5b879a76ee63dafa5f895a0e451a033bf35efce591b3
6
+ metadata.gz: dac1051680d2b3c69473636a9babd19b8799ea6e2eaadbb26582836641f7a73e843e4a26c32f41206edb0a6b21ab89b9b62cc08087360d75a562c3b6bb40188d
7
+ data.tar.gz: 52ca1f46ff0d459f450e1a1bd82b6efce780e9b6480ebbda955722eef4bea3a98d71cdaff076691b4cfe93e77c42285f358bfb4ba9adf857c961108302a4f5d6
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,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.1...HEAD
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.2)
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.6.3.1)
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
- - 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
@@ -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
- - 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
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](#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`,
@@ -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
- @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