cpflow 3.0.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.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/check_cpln_links.yml +19 -0
  3. data/.github/workflows/command_docs.yml +24 -0
  4. data/.github/workflows/rspec-shared.yml +56 -0
  5. data/.github/workflows/rspec.yml +28 -0
  6. data/.github/workflows/rubocop.yml +24 -0
  7. data/.gitignore +18 -0
  8. data/.overcommit.yml +16 -0
  9. data/.rubocop.yml +22 -0
  10. data/.simplecov_spawn.rb +10 -0
  11. data/CHANGELOG.md +259 -0
  12. data/CONTRIBUTING.md +73 -0
  13. data/Gemfile +7 -0
  14. data/Gemfile.lock +126 -0
  15. data/LICENSE +21 -0
  16. data/README.md +546 -0
  17. data/Rakefile +21 -0
  18. data/bin/cpflow +6 -0
  19. data/cpflow +6 -0
  20. data/cpflow.gemspec +41 -0
  21. data/docs/assets/grafana-alert.png +0 -0
  22. data/docs/assets/memcached.png +0 -0
  23. data/docs/assets/sidekiq-pre-stop-hook.png +0 -0
  24. data/docs/commands.md +454 -0
  25. data/docs/dns.md +15 -0
  26. data/docs/migrating.md +262 -0
  27. data/docs/postgres.md +436 -0
  28. data/docs/redis.md +128 -0
  29. data/docs/secrets-and-env-values.md +42 -0
  30. data/docs/tips.md +150 -0
  31. data/docs/troubleshooting.md +6 -0
  32. data/examples/circleci.yml +104 -0
  33. data/examples/controlplane.yml +159 -0
  34. data/lib/command/apply_template.rb +209 -0
  35. data/lib/command/base.rb +540 -0
  36. data/lib/command/build_image.rb +49 -0
  37. data/lib/command/cleanup_images.rb +136 -0
  38. data/lib/command/cleanup_stale_apps.rb +79 -0
  39. data/lib/command/config.rb +48 -0
  40. data/lib/command/copy_image_from_upstream.rb +108 -0
  41. data/lib/command/delete.rb +149 -0
  42. data/lib/command/deploy_image.rb +56 -0
  43. data/lib/command/doctor.rb +47 -0
  44. data/lib/command/env.rb +22 -0
  45. data/lib/command/exists.rb +23 -0
  46. data/lib/command/generate.rb +45 -0
  47. data/lib/command/info.rb +222 -0
  48. data/lib/command/latest_image.rb +19 -0
  49. data/lib/command/logs.rb +49 -0
  50. data/lib/command/maintenance.rb +42 -0
  51. data/lib/command/maintenance_off.rb +62 -0
  52. data/lib/command/maintenance_on.rb +62 -0
  53. data/lib/command/maintenance_set_page.rb +34 -0
  54. data/lib/command/no_command.rb +23 -0
  55. data/lib/command/open.rb +33 -0
  56. data/lib/command/open_console.rb +26 -0
  57. data/lib/command/promote_app_from_upstream.rb +38 -0
  58. data/lib/command/ps.rb +41 -0
  59. data/lib/command/ps_restart.rb +37 -0
  60. data/lib/command/ps_start.rb +51 -0
  61. data/lib/command/ps_stop.rb +82 -0
  62. data/lib/command/ps_wait.rb +40 -0
  63. data/lib/command/run.rb +573 -0
  64. data/lib/command/setup_app.rb +113 -0
  65. data/lib/command/test.rb +23 -0
  66. data/lib/command/version.rb +18 -0
  67. data/lib/constants/exit_code.rb +7 -0
  68. data/lib/core/config.rb +316 -0
  69. data/lib/core/controlplane.rb +552 -0
  70. data/lib/core/controlplane_api.rb +170 -0
  71. data/lib/core/controlplane_api_direct.rb +112 -0
  72. data/lib/core/doctor_service.rb +104 -0
  73. data/lib/core/helpers.rb +26 -0
  74. data/lib/core/shell.rb +100 -0
  75. data/lib/core/template_parser.rb +76 -0
  76. data/lib/cpflow/version.rb +6 -0
  77. data/lib/cpflow.rb +288 -0
  78. data/lib/deprecated_commands.json +9 -0
  79. data/lib/generator_templates/Dockerfile +27 -0
  80. data/lib/generator_templates/controlplane.yml +62 -0
  81. data/lib/generator_templates/entrypoint.sh +8 -0
  82. data/lib/generator_templates/templates/app.yml +21 -0
  83. data/lib/generator_templates/templates/postgres.yml +176 -0
  84. data/lib/generator_templates/templates/rails.yml +36 -0
  85. data/rakelib/create_release.rake +81 -0
  86. data/script/add_command +37 -0
  87. data/script/check_command_docs +3 -0
  88. data/script/check_cpln_links +45 -0
  89. data/script/rename_command +43 -0
  90. data/script/update_command_docs +62 -0
  91. data/templates/app.yml +13 -0
  92. data/templates/daily-task.yml +32 -0
  93. data/templates/maintenance.yml +25 -0
  94. data/templates/memcached.yml +24 -0
  95. data/templates/postgres.yml +32 -0
  96. data/templates/rails.yml +27 -0
  97. data/templates/redis.yml +21 -0
  98. data/templates/redis2.yml +37 -0
  99. data/templates/sidekiq.yml +38 -0
  100. 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
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/cpflow"
5
+
6
+ Cpflow::Cli.start
data/cpflow ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "lib/cpflow"
5
+
6
+ Cpflow::Cli.start
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