cpflow 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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