cpflow 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/check_cpln_links.yml +19 -0
- data/.github/workflows/command_docs.yml +24 -0
- data/.github/workflows/rspec-shared.yml +56 -0
- data/.github/workflows/rspec.yml +28 -0
- data/.github/workflows/rubocop.yml +24 -0
- data/.gitignore +18 -0
- data/.overcommit.yml +16 -0
- data/.rubocop.yml +22 -0
- data/.simplecov_spawn.rb +10 -0
- data/CHANGELOG.md +259 -0
- data/CONTRIBUTING.md +73 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +126 -0
- data/LICENSE +21 -0
- data/README.md +546 -0
- data/Rakefile +21 -0
- data/bin/cpflow +6 -0
- data/cpflow +6 -0
- data/cpflow.gemspec +41 -0
- data/docs/assets/grafana-alert.png +0 -0
- data/docs/assets/memcached.png +0 -0
- data/docs/assets/sidekiq-pre-stop-hook.png +0 -0
- data/docs/commands.md +454 -0
- data/docs/dns.md +15 -0
- data/docs/migrating.md +262 -0
- data/docs/postgres.md +436 -0
- data/docs/redis.md +128 -0
- data/docs/secrets-and-env-values.md +42 -0
- data/docs/tips.md +150 -0
- data/docs/troubleshooting.md +6 -0
- data/examples/circleci.yml +104 -0
- data/examples/controlplane.yml +159 -0
- data/lib/command/apply_template.rb +209 -0
- data/lib/command/base.rb +540 -0
- data/lib/command/build_image.rb +49 -0
- data/lib/command/cleanup_images.rb +136 -0
- data/lib/command/cleanup_stale_apps.rb +79 -0
- data/lib/command/config.rb +48 -0
- data/lib/command/copy_image_from_upstream.rb +108 -0
- data/lib/command/delete.rb +149 -0
- data/lib/command/deploy_image.rb +56 -0
- data/lib/command/doctor.rb +47 -0
- data/lib/command/env.rb +22 -0
- data/lib/command/exists.rb +23 -0
- data/lib/command/generate.rb +45 -0
- data/lib/command/info.rb +222 -0
- data/lib/command/latest_image.rb +19 -0
- data/lib/command/logs.rb +49 -0
- data/lib/command/maintenance.rb +42 -0
- data/lib/command/maintenance_off.rb +62 -0
- data/lib/command/maintenance_on.rb +62 -0
- data/lib/command/maintenance_set_page.rb +34 -0
- data/lib/command/no_command.rb +23 -0
- data/lib/command/open.rb +33 -0
- data/lib/command/open_console.rb +26 -0
- data/lib/command/promote_app_from_upstream.rb +38 -0
- data/lib/command/ps.rb +41 -0
- data/lib/command/ps_restart.rb +37 -0
- data/lib/command/ps_start.rb +51 -0
- data/lib/command/ps_stop.rb +82 -0
- data/lib/command/ps_wait.rb +40 -0
- data/lib/command/run.rb +573 -0
- data/lib/command/setup_app.rb +113 -0
- data/lib/command/test.rb +23 -0
- data/lib/command/version.rb +18 -0
- data/lib/constants/exit_code.rb +7 -0
- data/lib/core/config.rb +316 -0
- data/lib/core/controlplane.rb +552 -0
- data/lib/core/controlplane_api.rb +170 -0
- data/lib/core/controlplane_api_direct.rb +112 -0
- data/lib/core/doctor_service.rb +104 -0
- data/lib/core/helpers.rb +26 -0
- data/lib/core/shell.rb +100 -0
- data/lib/core/template_parser.rb +76 -0
- data/lib/cpflow/version.rb +6 -0
- data/lib/cpflow.rb +288 -0
- data/lib/deprecated_commands.json +9 -0
- data/lib/generator_templates/Dockerfile +27 -0
- data/lib/generator_templates/controlplane.yml +62 -0
- data/lib/generator_templates/entrypoint.sh +8 -0
- data/lib/generator_templates/templates/app.yml +21 -0
- data/lib/generator_templates/templates/postgres.yml +176 -0
- data/lib/generator_templates/templates/rails.yml +36 -0
- data/rakelib/create_release.rake +81 -0
- data/script/add_command +37 -0
- data/script/check_command_docs +3 -0
- data/script/check_cpln_links +45 -0
- data/script/rename_command +43 -0
- data/script/update_command_docs +62 -0
- data/templates/app.yml +13 -0
- data/templates/daily-task.yml +32 -0
- data/templates/maintenance.yml +25 -0
- data/templates/memcached.yml +24 -0
- data/templates/postgres.yml +32 -0
- data/templates/rails.yml +27 -0
- data/templates/redis.yml +21 -0
- data/templates/redis2.yml +37 -0
- data/templates/sidekiq.yml +38 -0
- metadata +341 -0
data/README.md
ADDED
@@ -0,0 +1,546 @@
|
|
1
|
+
# The power of Kubernetes with the ease of Heroku!
|
2
|
+
|
3
|
+
<meta name="author" content="Justin Gordon and Sergey Tarasov">
|
4
|
+
<meta name="description" content="Instructions on how to migrate from Heroku to Control Plane and a CLI called cpflow to make it easier.">
|
5
|
+
<meta name="copyright" content="ShakaCode, 2023">
|
6
|
+
<meta name="keywords" content="Control Plane, Heroku, Kubernetes, K8, Infrastructure">
|
7
|
+
<meta name="google-site-verification" content="dIV4nMplcYl6YOKOaZMqgvdKXhLJ4cdYY6pS6e_YrPU" />
|
8
|
+
|
9
|
+
[![RSpec](https://github.com/shakacode/control-plane-flow/actions/workflows/rspec.yml/badge.svg)](https://github.com/shakacode/control-plane-flow/actions/workflows/rspec.yml)
|
10
|
+
[![Rubocop](https://github.com/shakacode/control-plane-flow/actions/workflows/rubocop.yml/badge.svg)](https://github.com/shakacode/control-plane-flow/actions/workflows/rubocop.yml)
|
11
|
+
|
12
|
+
[![Gem](https://badge.fury.io/rb/cpflow.svg)](https://badge.fury.io/rb/cpflow)
|
13
|
+
|
14
|
+
|
15
|
+
Here's a playbook for migrating from [Heroku Flow](https://www.heroku.com/flow) to [Control Plane](https://shakacode.controlplane.com) with our `cpflow` gem source code.
|
16
|
+
|
17
|
+
----
|
18
|
+
|
19
|
+
_If you need a free demo account for Control Plane (no CC required), you can contact [Justin Gordon, CEO of ShakaCode](mailto:justin@shakacode.com)._
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
Be sure to see the [demo app](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane)
|
24
|
+
If you would like to see the simple YAML configuration and setup,
|
25
|
+
Also, check [how the `cpflow` gem (this project) is used in the Github actions](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.github/actions/deploy-to-control-plane/action.yml).
|
26
|
+
Here is a brief [video overview](https://www.youtube.com/watch?v=llaQoAV_6Iw).
|
27
|
+
|
28
|
+
---
|
29
|
+
|
30
|
+
This playbook shows how to move "Heroku apps" to "Control Plane workloads" via an open-source `cpflow` CLI on top of
|
31
|
+
Control Plane's `cpln` CLI.
|
32
|
+
|
33
|
+
Heroku provides a UX and CLI that enables easy publishing of Ruby on Rails and other apps. This ease of use comes via
|
34
|
+
many "Heroku" abstractions and naming conventions.
|
35
|
+
|
36
|
+
Control Plane, on the other hand, gives you access to raw cloud computing power. However, you need to know precisely how
|
37
|
+
to use it.
|
38
|
+
|
39
|
+
To simplify migration to and usage of Control Plane for Heroku users, this repository provides a **concept mapping** and
|
40
|
+
a **helper CLI** based on templates to save lots of day-to-day typing (and human errors).
|
41
|
+
|
42
|
+
1. [Key Features](#key-features)
|
43
|
+
2. [Concept Mapping](#concept-mapping)
|
44
|
+
3. [Installation](#installation)
|
45
|
+
4. [Steps to Migrate](#steps-to-migrate)
|
46
|
+
5. [Configuration Files](#configuration-files)
|
47
|
+
6. [Workflow](#workflow)
|
48
|
+
7. [Environment](#environment)
|
49
|
+
8. [Database](#database)
|
50
|
+
9. [In-memory Databases](#in-memory-databases)
|
51
|
+
10. [Scheduled Jobs](#scheduled-jobs)
|
52
|
+
11. [CLI Commands Reference](#cli-commands-reference)
|
53
|
+
12. [Mapping of Heroku Commands to `cpflow` and `cpln`](#mapping-of-heroku-commands-to-cpflow-and-cpln)
|
54
|
+
13. [Examples](#examples)
|
55
|
+
14. [Migrating Postgres Database from Heroku Infrastructure](/docs/postgres.md)
|
56
|
+
15. [Migrating Redis Database from Heroku Infrastructure](/docs/redis.md)
|
57
|
+
16. [Tips](/docs/tips.md)
|
58
|
+
|
59
|
+
## Key Features
|
60
|
+
|
61
|
+
- A `cpflow` command to complement the default Control Plane `cpln` command with "Heroku style scripting." The Ruby source
|
62
|
+
can serve as inspiration for your own scripts.
|
63
|
+
- Easy to understand Heroku to Control Plane conventions in setup and naming.
|
64
|
+
- **Safe, production-ready** equivalents of `heroku run` and `heroku run:detached` for Control Plane.
|
65
|
+
- Automatic sequential release tagging for Docker images.
|
66
|
+
- A project-aware CLI that enables working on multiple projects.
|
67
|
+
|
68
|
+
## Concept Mapping
|
69
|
+
|
70
|
+
On Heroku, everything runs as an app, which means an entity that:
|
71
|
+
|
72
|
+
- runs code from a Git repository.
|
73
|
+
- runs several process types, as defined in the `Procfile`.
|
74
|
+
- has dynos, which are Linux containers that run these process types.
|
75
|
+
- has add-ons, including the database and other services.
|
76
|
+
- has common environment variables.
|
77
|
+
|
78
|
+
On Control Plane, we can map a Heroku app to a GVC (Global Virtual Cloud). Such a cloud consists of workloads, which can
|
79
|
+
be anything that can run as a container.
|
80
|
+
|
81
|
+
| Heroku | Control Plane |
|
82
|
+
| ---------------- | ------------------------------------------- |
|
83
|
+
| _app_ | _GVC_ (Global Virtual Cloud) |
|
84
|
+
| _dyno_ | _workload_ |
|
85
|
+
| _add-on_ | either a _workload_ or an external resource |
|
86
|
+
| _review app_ | _GVC (app)_ in staging _organization_ |
|
87
|
+
| _staging env_ | _GVC (app)_ in staging _organization_ |
|
88
|
+
| _production env_ | _GVC (app)_ in production _organization_ |
|
89
|
+
|
90
|
+
On Heroku, dyno types are specified in the `Procfile` and configured via the CLI/UI; add-ons are configured only via the
|
91
|
+
CLI/UI.
|
92
|
+
|
93
|
+
On Control Plane, workloads are created either by _templates_ (preferred way) or via the CLI/UI.
|
94
|
+
|
95
|
+
For the typical Rails app, this means:
|
96
|
+
|
97
|
+
| Function | Examples | On Heroku | On Control Plane |
|
98
|
+
| --------------- | -------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------- |
|
99
|
+
| web traffic | `rails`, `sinatra` | `web` dyno | workload with app image |
|
100
|
+
| background jobs | `sidekiq`, `resque` | `worker` dyno | workload with app image |
|
101
|
+
| db | `postgres`, `mysql` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
|
102
|
+
| in-memory db | `redis`, `memcached` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
|
103
|
+
| others | `mailtrap` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
|
104
|
+
|
105
|
+
## Installation
|
106
|
+
|
107
|
+
1. Ensure your [Control Plane](https://shakacode.controlplane.com/) account is set up. Set up an `organization` `<your-org>` for testing in that account and modify the value for `aliases.common.cpln_org` in `.controlplane/controlplane.yml`, or you can also set it with the `CPLN_ORG` environment variable. If you need an organization, please [contact Shakacode](mailto:controlplane@shakacode.com).
|
108
|
+
|
109
|
+
2. Install [Node.js](https://nodejs.org/en) (required for Control Plane CLI).
|
110
|
+
|
111
|
+
3. Install [Ruby](https://www.ruby-lang.org/en/) (required for these helpers).
|
112
|
+
|
113
|
+
4. Install Control Plane CLI, and configure access ([docs here](https://shakadocs.controlplane.com/quickstart/quick-start-3-cli#getting-started-with-the-cli)).
|
114
|
+
|
115
|
+
```sh
|
116
|
+
# Install CLI
|
117
|
+
npm install -g @controlplane/cli
|
118
|
+
|
119
|
+
# Configure access
|
120
|
+
cpln login
|
121
|
+
|
122
|
+
# Update CLI
|
123
|
+
npm update -g @controlplane/cli
|
124
|
+
```
|
125
|
+
|
126
|
+
5. Run `cpln image docker-login --org <your-org>` to ensure that you have access to the Control Plane Docker registry.
|
127
|
+
|
128
|
+
6. Install Control Plane Flow `cpflow` CLI as a [Ruby gem](https://rubygems.org/gems/cpflow): `gem install cpflow`. If you want to use `cpflow` from Rake tasks in a Rails project, use `Bundler.with_unbundled_env { `cpflow help` } or else you'll get an error that `cpflow` cannot be found. While you can add `cpflow` to your Gemfile, it's not recommended because it might trigger conflicts with other gems.
|
129
|
+
|
130
|
+
7. You can use [this Dockerfile](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile) as an example for your project. Ensure that you have Docker running.
|
131
|
+
|
132
|
+
**Note:** Do not confuse the `cpflow` CLI with the `cpln` CLI. The `cpflow` CLI is the Control Plane Flow playbook CLI.
|
133
|
+
The `cpln` CLI is the Control Plane CLI.
|
134
|
+
|
135
|
+
## Steps to Migrate
|
136
|
+
|
137
|
+
Click [here](/docs/migrating.md) to see the steps to migrate.
|
138
|
+
|
139
|
+
## Configuration Files
|
140
|
+
|
141
|
+
The `cpflow` gem is based on several configuration files within a `/.controlplane` top-level directory in your project.
|
142
|
+
|
143
|
+
```
|
144
|
+
.controlplane/
|
145
|
+
├─ templates/
|
146
|
+
│ ├─ app.yml
|
147
|
+
│ ├─ postgres.yml
|
148
|
+
│ ├─ rails.yml
|
149
|
+
├─ controlplane.yml
|
150
|
+
├─ Dockerfile
|
151
|
+
├─ entrypoint.sh
|
152
|
+
```
|
153
|
+
|
154
|
+
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.
|
155
|
+
2. `Dockerfile` builds the production application. `entrypoint.sh` is an _example_ entrypoint script for the production application, referenced in your Dockerfile.
|
156
|
+
3. `templates` directory contains the templates for the various workloads, such as `rails.yml` and `postgres.yml`.
|
157
|
+
4. `templates/app.yml` defines your project's GVC (like a Heroku app). More importantly, it contains ENV values for the app.
|
158
|
+
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.
|
159
|
+
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.
|
160
|
+
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.
|
161
|
+
|
162
|
+
Here's a complete example of all supported config keys explained for the `controlplane.yml` file:
|
163
|
+
|
164
|
+
### `controlplane.yml`
|
165
|
+
|
166
|
+
```yaml
|
167
|
+
# Keys beginning with "cpln_" correspond to your settings in Control Plane.
|
168
|
+
|
169
|
+
# Global settings that apply to `cpflow` usage.
|
170
|
+
# You can opt out of allowing the use of CPLN_ORG and CPLN_APP env vars
|
171
|
+
# to avoid any accidents with the wrong org / app.
|
172
|
+
allow_org_override_by_env: true
|
173
|
+
allow_app_override_by_env: true
|
174
|
+
|
175
|
+
aliases:
|
176
|
+
common: &common
|
177
|
+
# Organization for staging and QA apps is typically set as an alias.
|
178
|
+
# Production apps will use a different organization, specified in `apps`, for security.
|
179
|
+
# Change this value to your organization name
|
180
|
+
# or set the CPLN_ORG env var and it will override this for all `cpflow` commands
|
181
|
+
# (provided that `allow_org_override_by_env` is set to `true`).
|
182
|
+
cpln_org: my-org-staging
|
183
|
+
|
184
|
+
# Control Plane offers the ability to use multiple locations.
|
185
|
+
# default_location is used for commands that require a location
|
186
|
+
# including `ps`, `run`, `apply-template`.
|
187
|
+
# This can be overridden with option --location=<location> and
|
188
|
+
# CPLN_LOCATION environment variable.
|
189
|
+
default_location: aws-us-east-2
|
190
|
+
|
191
|
+
# Allows running the command `cpflow setup-app`
|
192
|
+
# instead of `cpflow apply-template app redis postgres memcached rails sidekiq`.
|
193
|
+
#
|
194
|
+
# Note:
|
195
|
+
# 1. These names correspond to files in the `./controlplane/templates` directory.
|
196
|
+
# 2. Each file can contain many objects, such as in the case of templates that create a resource, like `postgres`.
|
197
|
+
# 3. While the naming often corresponds to a workload or other object name, the naming is arbitrary.
|
198
|
+
# Naming does not need to match anything other than the file name without the `.yml` extension.
|
199
|
+
setup_app_templates:
|
200
|
+
- app
|
201
|
+
- redis
|
202
|
+
- postgres
|
203
|
+
- memcached
|
204
|
+
- rails
|
205
|
+
- sidekiq
|
206
|
+
|
207
|
+
# Skips secrets setup when running `cpflow setup-app`.
|
208
|
+
skip_secrets_setup: true
|
209
|
+
|
210
|
+
# Only needed if using a custom secrets name.
|
211
|
+
# The default is '{APP_PREFIX}-secrets'. For example:
|
212
|
+
# - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
|
213
|
+
# it would be 'my-app-staging-secrets'
|
214
|
+
# - for an app 'my-app-review-1234' with `match_if_app_name_starts_with` set to `true`,
|
215
|
+
# it would be 'my-app-review-secrets'
|
216
|
+
secrets_name: my-secrets
|
217
|
+
|
218
|
+
# Only needed if using a custom secrets policy name.
|
219
|
+
# The default is '{APP_SECRETS}-policy'. For example:
|
220
|
+
# - for an app 'my-app-staging' with `match_if_app_name_starts_with` set to `false`,
|
221
|
+
# it would be 'my-app-staging-secrets-policy'
|
222
|
+
# - for an app 'my-app-review-1234' with `match_if_app_name_starts_with` set to `true`,
|
223
|
+
# it would be 'my-app-review-secrets-policy'
|
224
|
+
secrets_policy_name: my-secrets-policy
|
225
|
+
|
226
|
+
# Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
|
227
|
+
one_off_workload: rails
|
228
|
+
|
229
|
+
# Workloads that are for the application itself and are using application Docker images.
|
230
|
+
# These are updated with the new image when running the `deploy-image` command,
|
231
|
+
# and are also used by the `info` and `ps:` commands in order to get all of the defined workloads.
|
232
|
+
# On the other hand, if you have a workload for Redis, that would NOT use the application Docker image
|
233
|
+
# and not be listed here.
|
234
|
+
app_workloads:
|
235
|
+
- rails
|
236
|
+
- sidekiq
|
237
|
+
|
238
|
+
# Additional "service type" workloads, using non-application Docker images.
|
239
|
+
# These are only used by the `info` and `ps:` commands in order to get all of the defined workloads.
|
240
|
+
additional_workloads:
|
241
|
+
- redis
|
242
|
+
- postgres
|
243
|
+
- memcached
|
244
|
+
|
245
|
+
# Configure the workload name used when maintenance mode is on (defaults to "maintenance").
|
246
|
+
maintenance_workload: maintenance
|
247
|
+
|
248
|
+
# Fixes the remote terminal size to match the local terminal size
|
249
|
+
# when running `cpflow run`.
|
250
|
+
fix_terminal_size: true
|
251
|
+
|
252
|
+
# Sets a default CPU size for `cpflow 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 `cpflow 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 `cpflow run` jobs can execute before being stopped.
|
261
|
+
# If not specified, defaults to 21600 (6 hours).
|
262
|
+
runner_job_timeout: 1000
|
263
|
+
|
264
|
+
# Apps with a deployed image created before this amount of days will be listed for deletion
|
265
|
+
# when running the command `cpflow cleanup-stale-apps`.
|
266
|
+
stale_app_image_deployed_days: 5
|
267
|
+
|
268
|
+
# Images that exceed this quantity will be listed for deletion
|
269
|
+
# when running the command `cpflow cleanup-images`.
|
270
|
+
image_retention_max_qty: 20
|
271
|
+
|
272
|
+
# Images created before this amount of days will be listed for deletion
|
273
|
+
# when running the command `cpflow cleanup-images` (`image_retention_max_qty` takes precedence).
|
274
|
+
image_retention_days: 5
|
275
|
+
|
276
|
+
apps:
|
277
|
+
my-app-staging:
|
278
|
+
# Use the values from the common section above.
|
279
|
+
<<: *common
|
280
|
+
|
281
|
+
my-app-review:
|
282
|
+
<<: *common
|
283
|
+
|
284
|
+
# If `match_if_app_name_starts_with` is `true`, then use this config for app names starting with this name,
|
285
|
+
# e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
|
286
|
+
match_if_app_name_starts_with: true
|
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 `cpflow run` with the latest image.
|
290
|
+
hooks:
|
291
|
+
# Used by the command `cpflow setup-app` to run a hook after creating the app.
|
292
|
+
post_creation: bundle exec rake db:prepare
|
293
|
+
|
294
|
+
# Used by the command `cpflow delete` to run a hook before deleting the app.
|
295
|
+
pre_deletion: bundle exec rake db:drop
|
296
|
+
|
297
|
+
my-app-production:
|
298
|
+
<<: *common
|
299
|
+
|
300
|
+
# You can also opt out of allowing the use of CPLN_ORG and CPLN_APP env vars per app.
|
301
|
+
# It's recommended to leave this off for production, to avoid any accidents.
|
302
|
+
allow_org_override_by_env: false
|
303
|
+
allow_app_override_by_env: false
|
304
|
+
|
305
|
+
# Use a different organization for production.
|
306
|
+
cpln_org: my-org-production
|
307
|
+
|
308
|
+
# Allows running the command `cpflow promote-app-from-upstream -a my-app-production`
|
309
|
+
# to promote the staging app to production.
|
310
|
+
upstream: my-app-staging
|
311
|
+
|
312
|
+
# Used by the command `cpflow promote-app-from-upstream` to run a release script before deploying.
|
313
|
+
# This is relative to the `.controlplane/` directory.
|
314
|
+
release_script: release_script
|
315
|
+
|
316
|
+
# default_domain is used for commands that require a domain
|
317
|
+
# including `maintenance`, `maintenance:on`, `maintenance:off`.
|
318
|
+
default_domain: domain.com
|
319
|
+
|
320
|
+
my-app-other:
|
321
|
+
<<: *common
|
322
|
+
|
323
|
+
# You can specify a different `Dockerfile` relative to the `.controlplane/` directory (defaults to "Dockerfile").
|
324
|
+
dockerfile: ../some_other/Dockerfile
|
325
|
+
```
|
326
|
+
|
327
|
+
## Workflow
|
328
|
+
|
329
|
+
For a live example, see the [react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/readme.md) repository.
|
330
|
+
|
331
|
+
This example should closely match the below example.
|
332
|
+
|
333
|
+
Suppose your app is called `tutorial-app`. You can run the following commands.
|
334
|
+
|
335
|
+
### Setup Commands
|
336
|
+
|
337
|
+
```sh
|
338
|
+
# Provision all infrastructure on Control Plane.
|
339
|
+
# `tutorial-app` will be created per definition in .controlplane/controlplane.yml.
|
340
|
+
cpflow apply-template app postgres redis rails daily-task -a tutorial-app
|
341
|
+
|
342
|
+
# Build and push the Docker image to the Control Plane repository.
|
343
|
+
# Note, it may take many minutes. Be patient.
|
344
|
+
# Check for error messages, such as forgetting to run `cpln image docker-login --org <your-org>`.
|
345
|
+
cpflow build-image -a tutorial-app
|
346
|
+
|
347
|
+
# Promote the image to the app after running the `cpflow build-image` command.
|
348
|
+
# Note, the UX of the images may not show the image for up to 5 minutes. However, it's ready.
|
349
|
+
cpflow deploy-image -a tutorial-app
|
350
|
+
|
351
|
+
# See how the app is starting up.
|
352
|
+
cpflow logs -a tutorial-app
|
353
|
+
|
354
|
+
# Open the app in browser (once it has started up).
|
355
|
+
cpflow open -a tutorial-app
|
356
|
+
```
|
357
|
+
|
358
|
+
### Promoting Code Updates
|
359
|
+
|
360
|
+
After committing code, you will update your deployment of `tutorial-app` with the following commands:
|
361
|
+
|
362
|
+
```sh
|
363
|
+
# Build and push a new image with sequential image tagging, e.g. 'tutorial-app:1', then 'tutorial-app:2', etc.
|
364
|
+
cpflow build-image -a tutorial-app
|
365
|
+
|
366
|
+
# Run database migrations (or other release tasks) with the latest image,
|
367
|
+
# while the app is still running on the previous image.
|
368
|
+
# This is analogous to the release phase.
|
369
|
+
cpflow run -a tutorial-app --image latest -- rails db:migrate
|
370
|
+
|
371
|
+
# Pomote the latest image to the app.
|
372
|
+
cpflow deploy-image -a tutorial-app
|
373
|
+
```
|
374
|
+
|
375
|
+
If you needed to push a new image with a specific commit SHA, you can run the following command:
|
376
|
+
|
377
|
+
```sh
|
378
|
+
# Build and push with sequential image tagging and commit SHA, e.g. 'tutorial-app:123_ABCD', etc.
|
379
|
+
cpflow build-image -a tutorial-app --commit ABCD
|
380
|
+
```
|
381
|
+
|
382
|
+
### Real World
|
383
|
+
|
384
|
+
Most companies will configure their CI system to handle the above steps. Please [contact Shakacode](mailto:controlplane@shakacode.com) for examples of how to do this.
|
385
|
+
|
386
|
+
You can also join our [**Slack channel**](https://reactrails.slack.com/join/shared_invite/enQtNjY3NTczMjczNzYxLTlmYjdiZmY3MTVlMzU2YWE0OWM0MzNiZDI0MzdkZGFiZTFkYTFkOGVjODBmOWEyYWQ3MzA2NGE1YWJjNmVlMGE) for ShakaCode open source projects.
|
387
|
+
|
388
|
+
## Environment
|
389
|
+
|
390
|
+
There are two main places where we can set up environment variables in Control Plane:
|
391
|
+
|
392
|
+
- **In `workload/container/env`** - those are container-specific and must be set up individually for each container.
|
393
|
+
|
394
|
+
- **In `gvc/env`** - this is a "common" place to keep env vars which we can share among different workloads. Those
|
395
|
+
common variables are not visible by default, and we should explicitly enable them via the `inheritEnv` property.
|
396
|
+
|
397
|
+
Generally, `gvc/env` vars are useful for "app" types of workloads, e.g., `rails`, `sidekiq`, as they can easily share
|
398
|
+
common configs (the same way as on a Heroku app). They are not needed for non-app workloads, e.g., `redis`, `memcached`.
|
399
|
+
|
400
|
+
It is ok to keep most of the environment variables for non-production environments in the app templates as, in general,
|
401
|
+
they are not secret and can be committed to the repository.
|
402
|
+
|
403
|
+
It is also possible to set up a Secret store (of type `Dictionary`), which we can reference as, e.g.,
|
404
|
+
`cpln://secret/MY_SECRET_STORE_NAME/MY_SECRET_VAR_NAME`. In such a case, we must set up an app Identity and proper
|
405
|
+
Policy to access the secret.
|
406
|
+
|
407
|
+
In `templates/app.yml`:
|
408
|
+
|
409
|
+
```yaml
|
410
|
+
spec:
|
411
|
+
env:
|
412
|
+
- name: MY_GLOBAL_VAR
|
413
|
+
value: "value"
|
414
|
+
- name: MY_SECRET_GLOBAL_VAR
|
415
|
+
value: "cpln://secret/MY_SECRET_STORE_NAME/MY_SECRET_GLOBAL_VAR"
|
416
|
+
```
|
417
|
+
|
418
|
+
In `templates/rails.yml`:
|
419
|
+
|
420
|
+
```yaml
|
421
|
+
spec:
|
422
|
+
containers:
|
423
|
+
- name: rails
|
424
|
+
env:
|
425
|
+
- name: MY_LOCAL_VAR
|
426
|
+
value: "value"
|
427
|
+
- name: MY_SECRET_LOCAL_VAR
|
428
|
+
value: "cpln://secret/MY_SECRET_STORE_NAME/MY_SECRET_LOCAL_VAR"
|
429
|
+
inheritEnv: true # To enable global env inheritance.
|
430
|
+
```
|
431
|
+
|
432
|
+
## Database
|
433
|
+
|
434
|
+
There are several options for a database setup on Control Plane:
|
435
|
+
|
436
|
+
- **Heroku Postgres**. It is the least recommended but simplest. We only need to provision the Postgres add-on on Heroku
|
437
|
+
and copy its `XXXXXX_URL` connection string. This is good for quick testing but unsuitable for the long term.
|
438
|
+
|
439
|
+
- **Control Plane container**. We can set it up as a workload using one of the default
|
440
|
+
[Docker Hub](https://hub.docker.com/) images. However, such a setup lacks persistence between container restarts. We
|
441
|
+
can use this only for an example or test app where the database doesn't keep any serious data and where such data is
|
442
|
+
restorable.
|
443
|
+
|
444
|
+
- Any other cloud provider for Postgres, e.g., Amazon's RDS can be a quick go-to. Here are
|
445
|
+
[instructions for setting up a free tier of RDS](https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-rds-launch/).
|
446
|
+
|
447
|
+
**Tip:** If you are using RDS for development/testing purposes, you might consider running such a database publicly
|
448
|
+
accessible (Heroku actually does that for all of its Postgres databases unless they are within private spaces). Then we
|
449
|
+
can connect to such a database from everywhere with only the correct username/password.
|
450
|
+
|
451
|
+
By default, we have structured our templates to accomplish this with only a single free tier or low tier AWS RDS
|
452
|
+
instance that can serve all your development/testing needs for small/medium applications, e.g., as follows:
|
453
|
+
|
454
|
+
```sh
|
455
|
+
aws-rds-single-pg-instance
|
456
|
+
mydb-staging
|
457
|
+
mydb-review-111
|
458
|
+
mydb-review-222
|
459
|
+
mydb-review-333
|
460
|
+
```
|
461
|
+
|
462
|
+
Additionally, we provide a default `postgres` template in this repository optimized for Control Plane and suitable for
|
463
|
+
development purposes.
|
464
|
+
|
465
|
+
## In-memory Databases
|
466
|
+
|
467
|
+
E.g., Redis, Memcached.
|
468
|
+
|
469
|
+
For development purposes, it's useful to set those up as Control Plane workloads, as in most cases, they don't keep any
|
470
|
+
valuable data and can be safely restarted, which doesn't affect application performance.
|
471
|
+
|
472
|
+
For production purposes or where restarts are not an option, you should use external cloud services.
|
473
|
+
|
474
|
+
We provide default `redis` and `memcached` templates in this repository optimized for Control Plane and suitable for
|
475
|
+
development purposes.
|
476
|
+
|
477
|
+
## Scheduled Jobs
|
478
|
+
|
479
|
+
Control Plane supports scheduled jobs via [cron workloads](https://shakadocs.controlplane.com/reference/workload#cron).
|
480
|
+
|
481
|
+
Here's a partial example of a template for a cron workload, using the app image:
|
482
|
+
|
483
|
+
```yaml
|
484
|
+
kind: workload
|
485
|
+
name: daily-task
|
486
|
+
spec:
|
487
|
+
type: cron
|
488
|
+
job:
|
489
|
+
# Run daily job at 2am.
|
490
|
+
schedule: "0 2 * * *"
|
491
|
+
# "Never" or "OnFailure"
|
492
|
+
restartPolicy: Never
|
493
|
+
containers:
|
494
|
+
- name: daily-task
|
495
|
+
args:
|
496
|
+
- bundle
|
497
|
+
- exec
|
498
|
+
- rails
|
499
|
+
- db:prepare
|
500
|
+
image: "/org/APP_ORG/image/APP_IMAGE"
|
501
|
+
```
|
502
|
+
|
503
|
+
A complete example can be found at [templates/daily-task.yml](templates/daily-task.yml), optimized for Control Plane and
|
504
|
+
suitable for development purposes.
|
505
|
+
|
506
|
+
You can create the cron workload by adding the template for it to the `.controlplane/templates/` directory and running
|
507
|
+
`cpflow apply-template my-template -a my-app`, where `my-template` is the name of the template file (e.g., `my-template.yml`).
|
508
|
+
|
509
|
+
Then to view the logs of the cron workload, you can run `cpflow logs -a my-app -w my-template`.
|
510
|
+
|
511
|
+
## CLI Commands Reference
|
512
|
+
|
513
|
+
Click [here](/docs/commands.md) to see the commands.
|
514
|
+
|
515
|
+
You can also run the following command:
|
516
|
+
|
517
|
+
```sh
|
518
|
+
cpflow --help
|
519
|
+
```
|
520
|
+
|
521
|
+
## Mapping of Heroku Commands to `cpflow` and `cpln`
|
522
|
+
|
523
|
+
| Heroku Command | `cpflow` or `cpln` |
|
524
|
+
| -------------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
525
|
+
| [heroku ps](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-ps-type-type) | `cpflow ps` |
|
526
|
+
| [heroku config](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-config) | ? |
|
527
|
+
| [heroku maintenance](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-maintenance) | `cpflow maintenance` |
|
528
|
+
| [heroku logs](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-logs) | `cpflow logs` |
|
529
|
+
| [heroku pg](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-pg-database) | ? |
|
530
|
+
| [heroku pipelines:promote](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-pipelines-promote) | `cpflow promote-app-from-upstream` |
|
531
|
+
| [heroku psql](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-psql-database) | ? |
|
532
|
+
| [heroku redis](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-redis-database) | ? |
|
533
|
+
| [heroku releases](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-releases) | ? |
|
534
|
+
|
535
|
+
## Examples
|
536
|
+
|
537
|
+
- See this repository's `examples/` and `templates/` directories.
|
538
|
+
- See the `.controlplane/` directory of this live example:
|
539
|
+
[react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane).
|
540
|
+
- See [how the `cpflow` gem is used in the Github actions](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.github/actions/deploy-to-control-plane/action.yml).
|
541
|
+
- Here is a brief [video overview](https://www.youtube.com/watch?v=llaQoAV_6Iw).
|
542
|
+
|
543
|
+
## Resources
|
544
|
+
* If you need a free demo account for Control Plane (no CC required), you can contact [Justin Gordon, CEO of ShakaCode](mailto:justin@shakacode.com).
|
545
|
+
* [Control Plane Site](https://shakacode.controlplane.com)
|
546
|
+
* [Join our Slack to Discuss Control Plane Flow](https://reactrails.slack.com/join/shared_invite/enQtNjY3NTczMjczNzYxLTlmYjdiZmY3MTVlMzU2YWE0OWM0MzNiZDI0MzdkZGFiZTFkYTFkOGVjODBmOWEyYWQ3MzA2NGE1YWJjNmVlMGE)
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
require "rubocop/rake_task"
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:rspec)
|
8
|
+
|
9
|
+
RuboCop::RakeTask.new
|
10
|
+
|
11
|
+
task default: %i[rspec rubocop]
|
12
|
+
|
13
|
+
desc "Checks if commands.md file is up to date"
|
14
|
+
task :check_command_docs do
|
15
|
+
sh "./script/check_command_docs"
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "Updates commands.md file"
|
19
|
+
task :update_command_docs do
|
20
|
+
sh "./script/update_command_docs"
|
21
|
+
end
|
data/bin/cpflow
ADDED
data/cpflow
ADDED
data/cpflow.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/cpflow/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "cpflow"
|
7
|
+
spec.version = Cpflow::VERSION
|
8
|
+
spec.authors = ["Justin Gordon", "Sergey Tarasov"]
|
9
|
+
spec.email = ["justin@shakacode.com", "sergey@shakacode.com"]
|
10
|
+
|
11
|
+
spec.summary = "Control Plane Flow"
|
12
|
+
spec.description = "CLI for providing Heroku-like platform-as-a-service on Control Plane"
|
13
|
+
spec.homepage = "https://github.com/shakacode/control-plane-flow"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.required_ruby_version = ">= 2.7.0"
|
17
|
+
|
18
|
+
spec.add_dependency "debug", "~> 1.7.1"
|
19
|
+
spec.add_dependency "dotenv", "~> 2.8.1"
|
20
|
+
spec.add_dependency "jwt", "~> 2.8.1"
|
21
|
+
spec.add_dependency "psych", "~> 5.1.0"
|
22
|
+
spec.add_dependency "thor", "~> 1.2.1"
|
23
|
+
|
24
|
+
spec.add_development_dependency "overcommit", "~> 0.60.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.12.0"
|
26
|
+
spec.add_development_dependency "rspec-retry", "~> 0.6.2"
|
27
|
+
spec.add_development_dependency "rubocop", "~> 1.45.0"
|
28
|
+
spec.add_development_dependency "rubocop-rake", "~> 0.6.0"
|
29
|
+
spec.add_development_dependency "rubocop-rspec", "~> 2.18.1"
|
30
|
+
spec.add_development_dependency "simplecov", "~> 0.22.0"
|
31
|
+
spec.add_development_dependency "timecop", "~> 0.9.6"
|
32
|
+
spec.add_development_dependency "webmock", "~> 3.18.1"
|
33
|
+
|
34
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |file|
|
35
|
+
file.match(%r{^(coverage|pkg|spec|tmp)/})
|
36
|
+
end
|
37
|
+
|
38
|
+
spec.executables = ["cpflow"]
|
39
|
+
|
40
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
41
|
+
end
|
Binary file
|
Binary file
|
Binary file
|