Skip to content

Commit

Permalink
Update templates naming (#159)
Browse files Browse the repository at this point in the history
* chore: rename 'gvc' templates to 'app' and add identity
* chore: add secrets policy to 'secrets' templates
* feat: add option to set custom name for secrets and secrets policy
* docs: update CHANGELOG.md
* remove empty file
  • Loading branch information
rafaelgomesxyz authored May 10, 2024
1 parent abbb3b6 commit 56420bb
Show file tree
Hide file tree
Showing 34 changed files with 186 additions and 101 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Changes since the last non-beta release.

_Please add entries here for your pull requests that are not yet released._

### Added

- Added option to set custom names for secrets and secrets policy, using `secrets_name` and `secrets_policy_name` in `controlplane.yml`. [PR 159](https://github.com/shakacode/heroku-to-control-plane/pull/159) by [Rafael Gomes](https://github.com/rafaelgomesxyz).

### Changed

- `deploy-image` command now raises an error if image does not exist. [PR 153](https://github.com/shakacode/heroku-to-control-plane/pull/153) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
Expand Down
7 changes: 7 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ We use real apps for the tests. You'll need to have full access to a Control Pla
CPLN_ORG=your-org-for-tests bundle exec rspec
```

Alternatively, you might have a `.envrc` file with:

```sh
export CPLN_ORG=shakacode-heroku-to-control-plane-ci
export RSPEC_RETRY_RETRY_COUNT=1
```

Tests are separated between fast and slow. Slow tests can take a long time and usually involve building / deploying images and waiting for workloads to be ready / not ready, so they should only be run once in a while.

If you add a slow test, tag it with `slow`. Tests without a `slow` tag are considered fast by default.
Expand Down
39 changes: 26 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ The `cpl` gem is based on several configuration files within a `/.controlplane`
```
.controlplane/
├─ templates/
│ ├─ gvc.yml
│ ├─ app.yml
│ ├─ postgres.yml
│ ├─ rails.yml
├─ controlplane.yml
Expand All @@ -154,8 +154,8 @@ The `cpl` gem is based on several configuration files within a `/.controlplane`
1. `controlplane.yml` describes the overall application. Be sure to have `<your-org>` as the value for `aliases.common.cpln_org`, or set it with the `CPLN_ORG` environment variable.
2. `Dockerfile` builds the production application. `entrypoint.sh` is an _example_ entrypoint script for the production application, referenced in your Dockerfile.
3. `templates` directory contains the templates for the various workloads, such as `rails.yml` and `postgres.yml`.
4. `templates/gvc.yml` defines your project's GVC (like a Heroku app). More importantly, it contains ENV values for the app.
5. `templates/rails.yml` defines your Rails workload. It may inherit ENV values from the parent GVC, which is populated from the `templates/gvc.yml`. This file also configures scaling, sizing, firewalls, and other workload-specific values.
4. `templates/app.yml` defines your project's GVC (like a Heroku app). More importantly, it contains ENV values for the app.
5. `templates/rails.yml` defines your Rails workload. It may inherit ENV values from the parent GVC, which is populated from the `templates/app.yml`. This file also configures scaling, sizing, firewalls, and other workload-specific values.
6. For other workloads (like lines in a Heroku `Procfile`), you create additional template files. For example, you can base a `templates/sidekiq.yml` on the `templates/rails.yml` file.
7. You can have other files in the `templates` directory, such as `redis.yml` and `postgres.yml`, which could setup Redis and Postgres for a testing application.

Expand Down Expand Up @@ -189,27 +189,40 @@ aliases:
default_location: aws-us-east-2

# Allows running the command `cpl setup-app`
# instead of `cpl apply-template gvc redis postgres memcached rails sidekiq`.
# instead of `cpl apply-template app redis postgres memcached rails sidekiq`.
#
# Note:
# 1. These names correspond to files in the `./controlplane/templates` directory.
# 2. Each file can contain many objects, such as in the case of templates that create a resource, like `postgres`.
# 3. While the naming often corresponds to a workload or other object name, the naming is arbitrary.
# Naming does not need to match anything other than the file name without the `.yml` extension.
#
# If you're going to use secrets, you need to apply the `secrets.yml` template separately (one-time setup):
# `cpl apply-template secrets -a my-app`
setup_app_templates:
- gvc

# These templates are only required if using secrets.
- identity
- secrets
- secrets-policy

- app
- redis
- postgres
- memcached
- rails
- sidekiq

# Only needed if using a custom secrets name.
# The default is '{APP_PREFIX}-secrets'. For example:
# - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
# it would be 'my-app-staging-secrets'
# - for an app 'my-app-review-1234' with `match_if_app_name_starts_with` set to `true`,
# it would be 'my-app-review-secrets'
secrets_name: my-secrets

# Only needed if using a custom secrets policy name.
# The default is '{APP_SECRETS}-policy'. For example:
# - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
# it would be 'my-app-staging-secrets-policy'
# - for an app 'my-app-review-1234' with `match_if_app_name_starts_with` set to `true`,
# it would be 'my-app-review-secrets-policy'
secrets_policy_name: my-secrets-policy

# Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
one_off_workload: rails

Expand Down Expand Up @@ -303,7 +316,7 @@ Suppose your app is called `tutorial-app`. You can run the following commands.
```sh
# Provision all infrastructure on Control Plane.
# `tutorial-app` will be created per definition in .controlplane/controlplane.yml.
cpl apply-template gvc postgres redis rails daily-task -a tutorial-app
cpl apply-template app postgres redis rails daily-task -a tutorial-app

# Build and push the Docker image to the Control Plane repository.
# Note, it may take many minutes. Be patient.
Expand Down Expand Up @@ -370,7 +383,7 @@ It is also possible to set up a Secret store (of type `Dictionary`), which we ca
`cpln://secret/MY_SECRET_STORE_NAME/MY_SECRET_VAR_NAME`. In such a case, we must set up an app Identity and proper
Policy to access the secret.

In `templates/gvc.yml`:
In `templates/app.yml`:

```yaml
spec:
Expand Down
2 changes: 1 addition & 1 deletion docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ This `-a` option is used in most of the commands and will pick all other app con
cpl apply-template redis -a $APP_NAME

# Applies several templates (practically creating full app).
cpl apply-template gvc postgres redis rails -a $APP_NAME
cpl apply-template app postgres redis rails -a $APP_NAME
```

### `build-image`
Expand Down
12 changes: 6 additions & 6 deletions docs/migrating.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ key, e.g.:
my-app-staging:
<<: *common
setup_app_templates:
- gvc
- app
- redis
- memcached
- rails
Expand All @@ -46,8 +46,8 @@ my-app-staging:
Note how the templates correspond to files in the `.controlplane/templates/` directory. These files will be used by the
`cpl setup-app` and `cpl apply-template` commands.

Ensure that env vars point to the Heroku add-ons in the template for the app (`.controlplane/templates/gvc.yml`). See
[this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/templates/gvc.yml).
Ensure that env vars point to the Heroku add-ons in the template for the app (`.controlplane/templates/app.yml`). See
[this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/templates/app.yml).

After that, create a Dockerfile in `.controlplane/Dockerfile` for your deployment. See
[this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile).
Expand All @@ -61,7 +61,7 @@ app_main_folder/
controlplane.yml
entrypoint.sh # App-specific - edit as needed.
templates/
gvc.yml
app.yml
memcached.yml
rails.yml
redis.yml
Expand Down Expand Up @@ -192,7 +192,7 @@ configure an entry for, e.g., `my-app-review`, and then create review apps start
<<: *common
match_if_app_name_starts_with: true
setup_app_templates:
- gvc
- app
- redis
- memcached
- rails
Expand Down Expand Up @@ -226,7 +226,7 @@ Then follow the same steps for the initial deployment or code upgrades.
### Database for Review Apps

For the review app resources, these should be handled as env vars in the template for the app
(`.controlplane/templates/gvc.yml`), .e.g.:
(`.controlplane/templates/app.yml`), .e.g.:

```yaml
- name: DATABASE_URL
Expand Down
24 changes: 13 additions & 11 deletions docs/tips.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,19 @@ level, which applies to your GVCs mapped to that org.

You can do this during the initial app setup, like this:

1. Add the templates for `identity`, `secrets` and `secrets-policy` to `.controlplane/templates`
2. Ensure that the templates are listed in `setup_app_templates` for the app in `.controlplane/controlplane.yml`
3. Run `cpl setup-app -a $APP_NAME`
4. The identity, secrets and secrets policy will be automatically created, along with the proper binding
5. In the upper left "Manage Org" menu, click on "Secrets"
6. Find the created secret (it will be in the `$APP_PREFIX-secrets` format) and add the secret env vars there
7. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/$APP_PREFIX-secrets.SOME_VAR`)

You can also do it manually after. Here is how you do this:

1. In the upper left "Manage Org" menu, click on "Secrets"
1. Add the templates for `app` and `secrets` to `.controlplane/templates`
2. Ensure that the `app` template includes the `identity`
3. Ensure that the `app` template is listed in `setup_app_templates` for the app in `.controlplane/controlplane.yml`
4. Run `cpl apply-template secrets -a $APP_NAME` (one-time setup)
5. Run `cpl setup-app -a $APP_NAME`
6. The secrets, secrets policy and identity will be automatically created, along with the proper binding
7. In the Control Plane console, upper left "Manage Org" menu, click on "Secrets"
8. Find the created secret (it will be in the `$APP_PREFIX-secrets` format) and add the secret env vars there
9. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/$APP_PREFIX-secrets.SOME_VAR`)

Here are the manual steps for reference. We recommend that you follow the steps above:

1. In the upper left of the Control Plane console, "Manage Org" menu, click on "Secrets"
2. Create a secret with `Secret Type: Dictionary` (e.g., `my-secrets`) and add the secret env vars there
3. In the upper left "Manage GVC" menu, click on "Identities"
4. Create an identity (e.g., `my-identity`)
Expand Down
29 changes: 21 additions & 8 deletions examples/controlplane.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,40 @@ aliases:
default_location: aws-us-east-2

# Allows running the command `cpl setup-app`
# instead of `cpl apply-template gvc redis postgres memcached rails sidekiq`.
# instead of `cpl apply-template app redis postgres memcached rails sidekiq`.
#
# Note:
# 1. These names correspond to files in the `./controlplane/templates` directory.
# 2. Each file can contain many objects, such as in the case of templates that create a resource, like `postgres`.
# 3. While the naming often corresponds to a workload or other object name, the naming is arbitrary.
# Naming does not need to match anything other than the file name without the `.yml` extension.
#
# If you're going to use secrets, you need to apply the `secrets.yml` template separately (one-time setup):
# `cpl apply-template secrets -a my-app`
setup_app_templates:
- gvc

# These templates are only required if using secrets.
- identity
- secrets
- secrets-policy

- app
- redis
- postgres
- memcached
- rails
- sidekiq

# Only needed if using a custom secrets name.
# The default is '{APP_PREFIX}-secrets'. For example:
# - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
# it would be 'my-app-staging-secrets'
# - for an app 'my-app-review-1234' with `match_if_app_name_starts_with` set to `true`,
# it would be 'my-app-review-secrets'
secrets_name: my-secrets

# Only needed if using a custom secrets policy name.
# The default is '{APP_SECRETS}-policy'. For example:
# - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
# it would be 'my-app-staging-secrets-policy'
# - for an app 'my-app-review-1234' with `match_if_app_name_starts_with` set to `true`,
# it would be 'my-app-review-secrets-policy'
secrets_policy_name: my-secrets-policy

# Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
one_off_workload: rails

Expand Down
4 changes: 2 additions & 2 deletions lib/command/apply_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ApplyTemplate < Base # rubocop:disable Metrics/ClassLength
cpl apply-template redis -a $APP_NAME
# Applies several templates (practically creating full app).
cpl apply-template gvc postgres redis rails -a $APP_NAME
cpl apply-template app postgres redis rails -a $APP_NAME
```
EX

Expand All @@ -50,7 +50,7 @@ def call # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, M
@asked_for_confirmation = false

pending_templates = templates.select do |template|
if template == "gvc"
if template == "app"
confirm_app(template)
else
confirm_workload(template)
Expand Down
4 changes: 2 additions & 2 deletions lib/command/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -503,11 +503,11 @@ def app_identity_link
end

def app_secrets
"#{config.app_prefix}-secrets"
config.current[:secrets_name] || "#{config.app_prefix}-secrets"
end

def app_secrets_policy
"#{app_secrets}-policy"
config.current[:secrets_policy_name] || "#{app_secrets}-policy"
end

def ensure_docker_running!
Expand Down
5 changes: 4 additions & 1 deletion lib/command/setup_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ def call # rubocop:disable Metrics/MethodLength
if cp.fetch_identity(app_identity).nil? || cp.fetch_policy(app_secrets_policy).nil?
raise "Can't bind identity to policy: identity '#{app_identity}' or " \
"policy '#{app_secrets_policy}' doesn't exist. " \
"Please create them or use `--skip-secret-access-binding` to ignore this message."
"Please create them or use `--skip-secret-access-binding` to ignore this message." \
"You can also set a custom secrets name with `secrets_name` " \
"and a custom secrets policy name with `secrets_policy_name` " \
"in the `.controlplane/controlplane.yml` file."
end

step("Binding identity to policy") do
Expand Down
File renamed without changes.
18 changes: 9 additions & 9 deletions spec/command/apply_template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let!(:app) { dummy_test_app }

it "raises error" do
result = run_cpl_command("apply-template", "gvc", "rails", "nonexistent", "-a", app)
result = run_cpl_command("apply-template", "app", "rails", "nonexistent", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Missing templates")
Expand All @@ -23,7 +23,7 @@
end

it "applies valid templates" do
result = run_cpl_command("apply-template", "gvc", "rails", "-a", app)
result = run_cpl_command("apply-template", "app", "rails", "-a", app)

expect(result[:status]).to eq(0)
expect(result[:stderr]).to include("Created items")
Expand All @@ -41,7 +41,7 @@
end

it "applies valid templates and fails to apply invalid templates" do
result = run_cpl_command("apply-template", "gvc", "invalid", "rails", "-a", app)
result = run_cpl_command("apply-template", "app", "invalid", "rails", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Created items")
Expand All @@ -53,7 +53,7 @@
end

it "replaces all variables correctly" do
apply_result = run_cpl_command("apply-template", "gvc-with-all-variables", "-a", app)
apply_result = run_cpl_command("apply-template", "app-with-all-variables", "-a", app)
env_result = run_cpl_command("env", "-a", app)

org = dummy_test_org
Expand All @@ -77,7 +77,7 @@
end

it "replaces deprecated variables correctly and warns about them" do
apply_result = run_cpl_command("apply-template", "gvc-with-deprecated-variables", "-a", app)
apply_result = run_cpl_command("apply-template", "app-with-deprecated-variables", "-a", app)
env_result = run_cpl_command("env", "-a", app)

org = dummy_test_org
Expand All @@ -103,18 +103,18 @@
it "asks for confirmation and does nothing" do
allow(Shell).to receive(:confirm).with(include("App '#{app}' already exists")).and_return(false)

result = run_cpl_command("apply-template", "gvc", "-a", app)
result = run_cpl_command("apply-template", "app", "-a", app)

expect(Shell).to have_received(:confirm).once
expect(result[:status]).to eq(0)
expect(result[:stderr]).to include("Skipped templates")
expect(result[:stderr]).to include("- gvc")
expect(result[:stderr]).to include("- app")
end

it "asks for confirmation and re-creates app" do
allow(Shell).to receive(:confirm).with(include("App '#{app}' already exists")).and_return(true)

result = run_cpl_command("apply-template", "gvc", "-a", app)
result = run_cpl_command("apply-template", "app", "-a", app)

expect(Shell).to have_received(:confirm).once
expect(result[:status]).to eq(0)
Expand All @@ -125,7 +125,7 @@
it "skips confirmation and re-creates app" do
allow(Shell).to receive(:confirm).and_return(false)

result = run_cpl_command("apply-template", "gvc", "-a", app, "--yes")
result = run_cpl_command("apply-template", "app", "-a", app, "--yes")

expect(Shell).not_to have_received(:confirm)
expect(result[:status]).to eq(0)
Expand Down
2 changes: 1 addition & 1 deletion spec/command/build_image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
let!(:app) { dummy_test_app }

before do
run_cpl_command!("apply-template", "gvc", "-a", app)
run_cpl_command!("apply-template", "app", "-a", app)
end

after do
Expand Down
Loading

0 comments on commit 56420bb

Please sign in to comment.