cpl 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +4 -4
- data/README.md +152 -125
- 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 +2 -2
- data/docs/tips.md +177 -0
- data/examples/circleci.yml +8 -9
- data/examples/controlplane.yml +16 -14
- data/lib/command/base.rb +1 -1
- data/lib/command/cleanup_stale_apps.rb +1 -0
- data/lib/cpl/version.rb +2 -1
- data/lib/cpl.rb +42 -1
- data/script/update_command_docs +2 -2
- data/templates/daily-task.yml +5 -4
- data/templates/maintenance.yml +4 -3
- data/templates/memcached.yml +3 -2
- data/templates/postgres.yml +3 -2
- data/templates/rails.yml +3 -2
- data/templates/redis.yml +2 -1
- data/templates/sidekiq.yml +13 -4
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da0cd8b4b3f57a141b2a148a35555069f4ff4135803e4ae95932cd3887e3a567
|
4
|
+
data.tar.gz: dab258fecce6a5948374057418959d736915ab69f84593e1b189c148f62f00be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31c5cfe13e647abf6f34f6b021c808c220db07a48cd223d0d277ad7814ab0942961a7b75c63d89c3c109e7ca670d478285e5289fdb9fe64ccd828917b7fccf22
|
7
|
+
data.tar.gz: 926431c8d7fb4c5f8ba7930a3a156d70718dcce6eb1c717e9859f5a8546900266e4267cee7c755ca4c99612fb1b574a7cbfdd6ca23a2fd5483c1eb3c743a83db
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cpl (1.0.
|
4
|
+
cpl (1.0.1)
|
5
5
|
debug (~> 1.7.1)
|
6
6
|
dotenv (~> 2.8.1)
|
7
7
|
psych (~> 5.1.0)
|
@@ -25,7 +25,7 @@ GEM
|
|
25
25
|
hashdiff (1.0.1)
|
26
26
|
iniparse (1.5.0)
|
27
27
|
io-console (0.6.0)
|
28
|
-
irb (1.
|
28
|
+
irb (1.7.0)
|
29
29
|
reline (>= 0.3.0)
|
30
30
|
json (2.6.3)
|
31
31
|
overcommit (0.60.0)
|
@@ -41,7 +41,7 @@ GEM
|
|
41
41
|
rainbow (3.1.1)
|
42
42
|
rake (13.0.6)
|
43
43
|
regexp_parser (2.6.2)
|
44
|
-
reline (0.3.
|
44
|
+
reline (0.3.5)
|
45
45
|
io-console (~> 0.5)
|
46
46
|
rexml (3.2.5)
|
47
47
|
rspec (3.12.0)
|
@@ -83,7 +83,7 @@ GEM
|
|
83
83
|
simplecov_json_formatter (~> 0.1)
|
84
84
|
simplecov-html (0.12.3)
|
85
85
|
simplecov_json_formatter (0.1.4)
|
86
|
-
stringio (3.0.
|
86
|
+
stringio (3.0.7)
|
87
87
|
thor (1.2.2)
|
88
88
|
timecop (0.9.6)
|
89
89
|
unicode-display_width (2.4.2)
|
data/README.md
CHANGED
@@ -13,49 +13,57 @@ _A playbook for migrating from [Heroku](https://heroku.com) to [Control Plane](h
|
|
13
13
|
|
14
14
|
[](https://badge.fury.io/rb/cpl)
|
15
15
|
|
16
|
-
This playbook shows how to move "Heroku apps" to "Control Plane workloads" via an open-source `cpl` CLI on top of
|
16
|
+
This playbook shows how to move "Heroku apps" to "Control Plane workloads" via an open-source `cpl` CLI on top of
|
17
|
+
Control Plane's `cpln` CLI.
|
17
18
|
|
18
|
-
Heroku provides a UX and CLI that enables easy publishing of Ruby on Rails and other apps. This ease of use comes via
|
19
|
-
|
19
|
+
Heroku provides a UX and CLI that enables easy publishing of Ruby on Rails and other apps. This ease of use comes via
|
20
|
+
many "Heroku" abstractions and naming conventions.
|
20
21
|
|
21
|
-
|
22
|
+
Control Plane, on the other hand, gives you access to raw cloud computing power. However, you need to know precisely how
|
23
|
+
to use it.
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
To simplify migration to and usage of Control Plane for Heroku users, this repository provides a **concept mapping** and
|
26
|
+
a **helper CLI** based on templates to save lots of day-to-day typing (and human errors).
|
27
|
+
|
28
|
+
1. [Key Features](#key-features)
|
29
|
+
2. [Concept Mapping](#concept-mapping)
|
25
30
|
3. [Installation](#installation)
|
26
|
-
4. [Example CLI
|
27
|
-
|
31
|
+
4. [Example CLI Flow for Application Build/Deployment](#example-cli-flow-for-application-builddeployment)
|
32
|
+
- [Initial Setup and Deployment](#initial-setup-and-deployment)
|
33
|
+
- [Promoting Code Upgrades](#promoting-code-upgrades)
|
34
|
+
5. [Example Project Modifications for Control Plane](#example-project-modifications-for-control-plane)
|
28
35
|
6. [Environment](#environment)
|
29
36
|
7. [Database](#database)
|
30
|
-
8. [In-memory
|
31
|
-
9. [Scheduled
|
32
|
-
10. [CLI
|
37
|
+
8. [In-memory Databases](#in-memory-databases)
|
38
|
+
9. [Scheduled Jobs](#scheduled-jobs)
|
39
|
+
10. [CLI Commands Reference](#cli-commands-reference)
|
33
40
|
11. [Mapping of Heroku Commands to `cpl` and `cpln`](#mapping-of-heroku-commands-to-cpl-and-cpln)
|
34
41
|
12. [Examples](#examples)
|
35
|
-
13. [Migrating Postgres
|
36
|
-
14. [Migrating Redis
|
42
|
+
13. [Migrating Postgres Database from Heroku Infrastructure](/docs/postgres.md)
|
43
|
+
14. [Migrating Redis Database from Heroku Infrastructure](/docs/redis.md)
|
44
|
+
15. [Tips](/docs/tips.md)
|
37
45
|
|
38
|
-
## Key
|
46
|
+
## Key Features
|
39
47
|
|
40
|
-
- A `cpl` command to complement the default Control Plane `cpln` command with "Heroku style scripting." The Ruby source
|
48
|
+
- A `cpl` command to complement the default Control Plane `cpln` command with "Heroku style scripting." The Ruby source
|
49
|
+
can serve as inspiration for your own scripts.
|
41
50
|
- Easy to understand Heroku to Control Plane conventions in setup and naming.
|
42
51
|
- **Safe, production-ready** equivalents of `heroku run` and `heroku run:detached` for Control Plane.
|
43
52
|
- Automatic sequential release tagging for Docker images.
|
44
|
-
- A project-aware CLI
|
53
|
+
- A project-aware CLI that enables working on multiple projects.
|
45
54
|
|
46
|
-
## Concept
|
55
|
+
## Concept Mapping
|
47
56
|
|
48
57
|
On Heroku, everything runs as an app, which means an entity that:
|
49
58
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
On Control Plane, we can map a Heroku app to a GVC (Global Virtual Cloud). Such a cloud consists of workloads, which can be anything that can run as a container.
|
59
|
+
- runs code from a Git repository.
|
60
|
+
- runs several process types, as defined in the `Procfile`.
|
61
|
+
- has dynos, which are Linux containers that run these process types.
|
62
|
+
- has add-ons, including the database and other services.
|
63
|
+
- has common environment variables.
|
57
64
|
|
58
|
-
|
65
|
+
On Control Plane, we can map a Heroku app to a GVC (Global Virtual Cloud). Such a cloud consists of workloads, which can
|
66
|
+
be anything that can run as a container.
|
59
67
|
|
60
68
|
| Heroku | Control Plane |
|
61
69
|
| ---------------- | ------------------------------------------- |
|
@@ -66,54 +74,61 @@ On Control Plane, we can map a Heroku app to a GVC (Global Virtual Cloud). Such
|
|
66
74
|
| _staging env_ | _GVC (app)_ in staging _organization_ |
|
67
75
|
| _production env_ | _GVC (app)_ in production _organization_ |
|
68
76
|
|
69
|
-
On Heroku, dyno types are specified in the `Procfile` and configured via the CLI/UI; add-ons are configured only via the
|
77
|
+
On Heroku, dyno types are specified in the `Procfile` and configured via the CLI/UI; add-ons are configured only via the
|
78
|
+
CLI/UI.
|
79
|
+
|
70
80
|
On Control Plane, workloads are created either by _templates_ (preferred way) or via the CLI/UI.
|
71
81
|
|
72
82
|
For the typical Rails app, this means:
|
73
83
|
|
74
|
-
| Function
|
75
|
-
|
|
76
|
-
| web traffic
|
77
|
-
| background jobs
|
78
|
-
| db
|
79
|
-
| in-memory db
|
80
|
-
|
|
84
|
+
| Function | Examples | On Heroku | On Control Plane |
|
85
|
+
| --------------- | -------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------- |
|
86
|
+
| web traffic | `rails`, `sinatra` | `web` dyno | workload with app image |
|
87
|
+
| background jobs | `sidekiq`, `resque` | `worker` dyno | workload with app image |
|
88
|
+
| db | `postgres`, `mysql` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
|
89
|
+
| in-memory db | `redis`, `memcached` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
|
90
|
+
| others | `mailtrap` | add-on | external provider or can be set up for development/testing with Docker image (lacks persistence between restarts) |
|
81
91
|
|
82
92
|
## Installation
|
83
93
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
2. Install `ruby` (required for these helpers).
|
88
|
-
3. Install Control Plane CLI (adds `cpln` command) and configure credentials by running command `cpln login`.
|
94
|
+
1. Install [Node.js](https://nodejs.org/en) (required for Control Plane CLI).
|
95
|
+
2. Install [Ruby](https://www.ruby-lang.org/en/) (required for these helpers).
|
96
|
+
3. Install Control Plane CLI (adds `cpln` command) and configure credentials.
|
89
97
|
|
90
98
|
```sh
|
91
99
|
npm install -g @controlplane/cli
|
92
100
|
cpln login
|
93
101
|
```
|
94
102
|
|
95
|
-
|
103
|
+
4. Install Heroku to Control Plane `cpl` CLI, either as a [Ruby gem](https://rubygems.org/gems/cpl) or a local clone.
|
104
|
+
For information on the latter, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
96
105
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
folder tree it runs. Thus, this automates running several projects with different configs without explicitly switching configs.
|
106
|
+
```sh
|
107
|
+
gem install cpl
|
108
|
+
```
|
101
109
|
|
102
|
-
|
110
|
+
**Note:** Do not confuse the `cpl` CLI with the `cpln` CLI. The `cpl` CLI is the Heroku to Control Plane playbook CLI.
|
111
|
+
The `cpln` CLI is the Control Plane CLI.
|
103
112
|
|
104
|
-
## Example CLI
|
113
|
+
## Example CLI Flow for Application Build/Deployment
|
105
114
|
|
106
115
|
**Notes:**
|
107
116
|
|
108
|
-
|
109
|
-
|
117
|
+
- `my-app` is an app name defined in the `.controlplane/controlplane.yml` file, such as `ror-tutorial` in
|
118
|
+
[this `controlplane.yml` file](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/controlplane.yml).
|
119
|
+
- Other files in the `.controlplane/templates/` directory are used by the `cpl setup-app` and `cpl apply-template`
|
120
|
+
commands.
|
110
121
|
|
111
122
|
### Initial Setup and Deployment
|
112
123
|
|
113
|
-
|
124
|
+
For each Git project that you want to deploy to Control Plane, copy project-specific configs to a `.controlplane/`
|
125
|
+
directory at the top of your project. `cpl` will pick those up depending on which project folder tree it runs. Thus,
|
126
|
+
this automates running several projects with different configs without explicitly switching configs.
|
127
|
+
|
128
|
+
Before the initial setup, add the templates for the app to `.controlplane/controlplane.yml`, using the `setup` key, e.g.:
|
114
129
|
|
115
130
|
```yaml
|
116
|
-
|
131
|
+
my-app:
|
117
132
|
setup:
|
118
133
|
- gvc
|
119
134
|
- postgres
|
@@ -123,59 +138,61 @@ myapp:
|
|
123
138
|
- sidekiq
|
124
139
|
```
|
125
140
|
|
126
|
-
Note how the templates correspond to files in the `.controlplane/templates
|
141
|
+
Note how the templates correspond to files in the `.controlplane/templates/` directory.
|
142
|
+
|
143
|
+
Then create a `Dockerfile` for your deployment. See
|
144
|
+
[this example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/Dockerfile).
|
127
145
|
|
128
146
|
```sh
|
129
147
|
# Provision infrastructure (one-time-only for new apps) using templates.
|
130
|
-
cpl setup-app -a
|
148
|
+
cpl setup-app -a my-app
|
131
149
|
|
132
|
-
# Build and push image with auto-tagging "
|
133
|
-
cpl build-image -a
|
150
|
+
# Build and push image with auto-tagging, e.g., "my-app:1_456".
|
151
|
+
cpl build-image -a my-app --commit 456
|
134
152
|
|
135
153
|
# Prepare database.
|
136
|
-
cpl run:detached
|
154
|
+
cpl run:detached -a my-app --image latest -- rails db:prepare
|
137
155
|
|
138
156
|
# Deploy latest image.
|
139
|
-
cpl deploy-image -a
|
157
|
+
cpl deploy-image -a my-app
|
140
158
|
|
141
159
|
# Open app in browser.
|
142
|
-
cpl open -a
|
160
|
+
cpl open -a my-app
|
143
161
|
```
|
144
162
|
|
145
|
-
### Promoting
|
163
|
+
### Promoting Code Upgrades
|
146
164
|
|
147
165
|
```sh
|
148
|
-
# Build and push new image with sequential
|
149
|
-
cpl build-image -a
|
166
|
+
# Build and push new image with sequential tagging, e.g., "my-app:2".
|
167
|
+
cpl build-image -a my-app
|
150
168
|
|
151
|
-
#
|
152
|
-
|
153
|
-
cpl build-image -a ror-tutorial --commit ABCD
|
169
|
+
# Or build and push new image with sequential tagging and commit SHA, e.g., "my-app:2_ABC".
|
170
|
+
cpl build-image -a my-app --commit ABC
|
154
171
|
|
155
|
-
# Run database migrations (or other release tasks) with latest image,
|
156
|
-
# while app is still running on previous image.
|
172
|
+
# Run database migrations (or other release tasks) with latest image, while app is still running on previous image.
|
157
173
|
# This is analogous to the release phase.
|
158
|
-
cpl run:detached
|
174
|
+
cpl run:detached -a my-app --image latest -- rails db:migrate
|
159
175
|
|
160
|
-
# Deploy latest image
|
161
|
-
cpl deploy-image -a
|
176
|
+
# Deploy latest image.
|
177
|
+
cpl deploy-image -a my-app
|
162
178
|
```
|
163
179
|
|
164
|
-
## Example
|
180
|
+
## Example Project Modifications for Control Plane
|
165
181
|
|
166
182
|
_See this for a complete example._
|
167
183
|
|
168
|
-
To learn how to migrate an app, we recommend
|
184
|
+
To learn how to migrate an app, we recommend following along with
|
185
|
+
[this example project](https://github.com/shakacode/react-webpack-rails-tutorial).
|
169
186
|
|
170
|
-
1. Create the `.controlplane
|
171
|
-
something as follows:
|
187
|
+
1. Create the `.controlplane/` directory at the top of your project and copy files from the `templates/` directory of
|
188
|
+
this repository to something as follows:
|
172
189
|
|
173
190
|
```sh
|
174
191
|
app_main_folder/
|
175
192
|
.controlplane/
|
176
193
|
Dockerfile # Your app's Dockerfile, with some Control Plane changes.
|
177
194
|
controlplane.yml
|
178
|
-
entrypoint.sh # App-specific
|
195
|
+
entrypoint.sh # App-specific - edit as needed.
|
179
196
|
templates/
|
180
197
|
gvc.yml
|
181
198
|
memcached.yml
|
@@ -185,9 +202,12 @@ app_main_folder/
|
|
185
202
|
sidekiq.yml
|
186
203
|
```
|
187
204
|
|
188
|
-
The example
|
205
|
+
The example
|
206
|
+
[`.controlplane/` directory](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane)
|
207
|
+
already contains these files.
|
189
208
|
|
190
|
-
2. Edit your `controlplane.yml` file as needed. For example, see
|
209
|
+
2. Edit your `controlplane.yml` file as needed. For example, see
|
210
|
+
[this `controlplane.yml` file](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/controlplane.yml).
|
191
211
|
|
192
212
|
```yaml
|
193
213
|
# Keys beginning with "cpln_" correspond to your settings in Control Plane.
|
@@ -195,11 +215,10 @@ The example [`.controlplane` directory](https://github.com/shakacode/react-webpa
|
|
195
215
|
aliases:
|
196
216
|
common: &common
|
197
217
|
# Organization name for staging (customize to your needs).
|
198
|
-
# Production apps will use a different
|
218
|
+
# Production apps will use a different organization, specified below, for security.
|
199
219
|
cpln_org: my-org-staging
|
200
220
|
|
201
221
|
# Example apps use only one location. Control Plane offers the ability to use multiple locations.
|
202
|
-
# TODO -- allow specification of multiple locations
|
203
222
|
default_location: aws-us-east-2
|
204
223
|
|
205
224
|
# Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
|
@@ -216,52 +235,58 @@ aliases:
|
|
216
235
|
- postgres
|
217
236
|
- memcached
|
218
237
|
|
238
|
+
# Configure the workload name used when maintenance mode is on (defaults to "maintenance")
|
239
|
+
maintenance_workload: maintenance
|
240
|
+
|
219
241
|
apps:
|
220
242
|
my-app-staging:
|
221
243
|
# Use the values from the common section above.
|
222
244
|
<<: *common
|
223
245
|
my-app-review:
|
224
246
|
<<: *common
|
225
|
-
# If `match_if_app_name_starts_with`
|
247
|
+
# If `match_if_app_name_starts_with` is `true`, then use this config for app names starting with this name,
|
226
248
|
# e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
|
227
249
|
match_if_app_name_starts_with: true
|
228
250
|
my-app-production:
|
229
251
|
<<: *common
|
230
252
|
# Use a different organization for production.
|
231
253
|
cpln_org: my-org-production
|
232
|
-
# Allows running the command `cpl promote-app-from-upstream -a my-app-production`
|
254
|
+
# Allows running the command `cpl promote-app-from-upstream -a my-app-production`
|
255
|
+
# to promote the staging app to production.
|
233
256
|
upstream: my-app-staging
|
234
257
|
my-app-other:
|
235
258
|
<<: *common
|
236
|
-
# You can specify a different `Dockerfile` relative to the `.controlplane
|
259
|
+
# You can specify a different `Dockerfile` relative to the `.controlplane/` directory (defaults to "Dockerfile").
|
237
260
|
dockerfile: ../some_other/Dockerfile
|
238
261
|
```
|
239
262
|
|
240
|
-
3. We recommend that you try out the commands listed in
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
263
|
+
3. We recommend that you try out the commands listed in
|
264
|
+
[the example](https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/.controlplane/readme.md).
|
265
|
+
These steps will guide you to the following:
|
266
|
+
|
267
|
+
1. Provision the GVC and workloads.
|
268
|
+
2. Build the Docker image.
|
269
|
+
3. Run Rails migrations, like in the Heroku release phase.
|
270
|
+
4. Promote the latest Docker image.
|
245
271
|
|
246
272
|
## Environment
|
247
273
|
|
248
274
|
There are two main places where we can set up environment variables in Control Plane:
|
249
275
|
|
250
|
-
- **In `workload/container/env`** - those are container-specific and
|
276
|
+
- **In `workload/container/env`** - those are container-specific and must be set up individually for each container.
|
251
277
|
|
252
|
-
- **In `gvc/env`** - this is a "common" place to keep env vars which we can share among different workloads.
|
253
|
-
|
278
|
+
- **In `gvc/env`** - this is a "common" place to keep env vars which we can share among different workloads. Those
|
279
|
+
common variables are not visible by default, and we should explicitly enable them via the `inheritEnv` property.
|
254
280
|
|
255
|
-
|
256
|
-
common configs (the same way as on a Heroku app). They are not needed for non-app workloads,
|
257
|
-
e.g., `redis`, `memcached`.
|
281
|
+
Generally, `gvc/env` vars are useful for "app" types of workloads, e.g., `rails`, `sidekiq`, as they can easily share
|
282
|
+
common configs (the same way as on a Heroku app). They are not needed for non-app workloads, e.g., `redis`, `memcached`.
|
258
283
|
|
259
284
|
It is ok to keep most of the environment variables for non-production environments in the app templates as, in general,
|
260
285
|
they are not secret and can be committed to the repository.
|
261
286
|
|
262
|
-
It is also possible to set up a Secret store (of type Dictionary), which we can reference as,
|
263
|
-
|
264
|
-
|
287
|
+
It is also possible to set up a Secret store (of type `Dictionary`), which we can reference as, e.g.,
|
288
|
+
`cpln://secret/MY_SECRET_STORE_NAME/MY_SECRET_VAR_NAME`. In such a case, we must set up an app Identity and proper
|
289
|
+
Policy to access the secret.
|
265
290
|
|
266
291
|
```yaml
|
267
292
|
# In `templates/gvc.yml`:
|
@@ -281,31 +306,32 @@ spec:
|
|
281
306
|
value: 'value'
|
282
307
|
- name: MY_SECRET_LOCAL_VAR
|
283
308
|
value: 'cpln://secret/MY_SECRET_STORE_NAME/MY_SECRET_LOCAL_VAR'
|
284
|
-
inheritEnv: true # To enable global env inheritance
|
309
|
+
inheritEnv: true # To enable global env inheritance.
|
285
310
|
```
|
286
311
|
|
287
312
|
## Database
|
288
313
|
|
289
314
|
There are several options for a database setup on Control Plane:
|
290
315
|
|
291
|
-
|
292
|
-
|
316
|
+
- **Heroku Postgres**. It is the least recommended but simplest. We only need to provision the Postgres add-on on Heroku
|
317
|
+
and copy its `XXXXXX_URL` connection string. This is good for quick testing but unsuitable for the long term.
|
293
318
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
319
|
+
- **Control Plane container**. We can set it up as a workload using one of the default
|
320
|
+
[Docker Hub](https://hub.docker.com/) images. However, such a setup lacks persistence between container restarts. We
|
321
|
+
can use this only for an example or test app where the database doesn't keep any serious data and where such data is
|
322
|
+
restorable.
|
298
323
|
|
299
|
-
|
324
|
+
- Any other cloud provider for Postgres, e.g., Amazon's RDS can be a quick go-to. Here are
|
325
|
+
[instructions for setting up a free tier of RDS](https://aws.amazon.com/premiumsupport/knowledge-center/free-tier-rds-launch/).
|
300
326
|
|
301
327
|
**Tip:** If you are using RDS for development/testing purposes, you might consider running such a database publicly
|
302
|
-
accessible (Heroku actually does that for all of its Postgres databases unless they are within private spaces). Then we
|
303
|
-
such a database from everywhere with only the correct username/password.
|
328
|
+
accessible (Heroku actually does that for all of its Postgres databases unless they are within private spaces). Then we
|
329
|
+
can connect to such a database from everywhere with only the correct username/password.
|
304
330
|
|
305
|
-
By default, we have structured our templates to accomplish this with only a single free tier or low tier AWS RDS
|
306
|
-
that can serve all your development/testing needs for small/medium applications, e.g., as follows:
|
331
|
+
By default, we have structured our templates to accomplish this with only a single free tier or low tier AWS RDS
|
332
|
+
instance that can serve all your development/testing needs for small/medium applications, e.g., as follows:
|
307
333
|
|
308
|
-
```
|
334
|
+
```sh
|
309
335
|
aws-rds-single-pg-instance
|
310
336
|
mydb-staging
|
311
337
|
mydb-review-111
|
@@ -313,22 +339,22 @@ aws-rds-single-pg-instance
|
|
313
339
|
mydb-review-333
|
314
340
|
```
|
315
341
|
|
316
|
-
Additionally, we provide a default `postgres` template in this
|
317
|
-
|
342
|
+
Additionally, we provide a default `postgres` template in this repository optimized for Control Plane and suitable for
|
343
|
+
development purposes.
|
318
344
|
|
319
|
-
## In-memory
|
345
|
+
## In-memory Databases
|
320
346
|
|
321
|
-
E.g
|
347
|
+
E.g., Redis, Memcached.
|
322
348
|
|
323
|
-
For development purposes, it's useful to set those up as Control Plane workloads, as in most cases they don't keep any
|
324
|
-
valuable data and can be safely restarted
|
349
|
+
For development purposes, it's useful to set those up as Control Plane workloads, as in most cases, they don't keep any
|
350
|
+
valuable data and can be safely restarted, which doesn't affect application performance.
|
325
351
|
|
326
352
|
For production purposes or where restarts are not an option, you should use external cloud services.
|
327
353
|
|
328
|
-
We provide default `redis` and `memcached` templates in this
|
329
|
-
|
354
|
+
We provide default `redis` and `memcached` templates in this repository optimized for Control Plane and suitable for
|
355
|
+
development purposes.
|
330
356
|
|
331
|
-
## Scheduled
|
357
|
+
## Scheduled Jobs
|
332
358
|
|
333
359
|
Control Plane supports scheduled jobs via [cron workloads](https://docs.controlplane.com/reference/workload#cron).
|
334
360
|
|
@@ -340,9 +366,9 @@ name: daily-task
|
|
340
366
|
spec:
|
341
367
|
type: cron
|
342
368
|
job:
|
343
|
-
# Run daily job at 2am
|
369
|
+
# Run daily job at 2am.
|
344
370
|
schedule: 0 2 * * *
|
345
|
-
# Never or OnFailure
|
371
|
+
# "Never" or "OnFailure"
|
346
372
|
restartPolicy: Never
|
347
373
|
containers:
|
348
374
|
- name: daily-task
|
@@ -354,17 +380,19 @@ spec:
|
|
354
380
|
image: "/org/APP_ORG/image/APP_IMAGE"
|
355
381
|
```
|
356
382
|
|
357
|
-
A complete example can be found at [templates/daily-task.yml](templates/daily-task.yml), optimized for Control Plane and
|
383
|
+
A complete example can be found at [templates/daily-task.yml](templates/daily-task.yml), optimized for Control Plane and
|
384
|
+
suitable for development purposes.
|
358
385
|
|
359
|
-
You can create the cron workload by adding the template for it to the `.controlplane/templates
|
386
|
+
You can create the cron workload by adding the template for it to the `.controlplane/templates/` directory and running
|
387
|
+
`cpl apply-template my-template -a my-app`, where `my-template` is the name of the template file (e.g., `my-template.yml`).
|
360
388
|
|
361
389
|
Then to view the logs of the cron workload, you can run `cpl logs -a my-app -w my-template`.
|
362
390
|
|
363
|
-
## CLI
|
391
|
+
## CLI Commands Reference
|
364
392
|
|
365
393
|
Click [here](/docs/commands.md) to see the commands.
|
366
394
|
|
367
|
-
You can also run:
|
395
|
+
You can also run the following command:
|
368
396
|
|
369
397
|
```sh
|
370
398
|
cpl --help
|
@@ -372,8 +400,6 @@ cpl --help
|
|
372
400
|
|
373
401
|
## Mapping of Heroku Commands to `cpl` and `cpln`
|
374
402
|
|
375
|
-
**`[WIP]`**
|
376
|
-
|
377
403
|
| Heroku Command | `cpl` or `cpln` |
|
378
404
|
| -------------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
379
405
|
| [heroku ps](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-ps-type-type) | `cpl ps` |
|
@@ -388,5 +414,6 @@ cpl --help
|
|
388
414
|
|
389
415
|
## Examples
|
390
416
|
|
391
|
-
|
392
|
-
|
417
|
+
- See the `examples/` and `templates/` directories of this repository.
|
418
|
+
- See the `.controlplane/` directory of this live example:
|
419
|
+
[react-webpack-rails-tutorial](https://github.com/shakacode/react-webpack-rails-tutorial/tree/master/.controlplane)
|
Binary file
|
Binary file
|
Binary file
|
data/docs/commands.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<!-- NOTE: This file is automatically generated by running `script/generate_commands_docs`. Do NOT edit it manually. -->
|
2
2
|
|
3
|
-
|
3
|
+
## Common Options
|
4
4
|
|
5
5
|
```
|
6
6
|
-a XXX, --app XXX app ref on Control Plane (GVC)
|
@@ -9,7 +9,7 @@
|
|
9
9
|
This `-a` option is used in most of the commands and will pick all other app configurations from the project-specific
|
10
10
|
`.controlplane/controlplane.yml` file.
|
11
11
|
|
12
|
-
|
12
|
+
## Commands
|
13
13
|
|
14
14
|
### `apply-template`
|
15
15
|
|
data/docs/tips.md
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
# Tips
|
2
|
+
|
3
|
+
1. [GVCs vs. Orgs](#gvcs-vs-orgs)
|
4
|
+
2. [RAM](#ram)
|
5
|
+
3. [Remote IP](#remote-ip)
|
6
|
+
4. [ENV Values](#env-values)
|
7
|
+
5. [CI](#ci)
|
8
|
+
6. [Memcached](#memcached)
|
9
|
+
7. [Sidekiq](#sidekiq)
|
10
|
+
- [Quieting Non-Critical Workers During Deployments](#quieting-non-critical-workers-during-deployments)
|
11
|
+
- [Setting Up a Pre Stop Hook](#setting-up-a-pre-stop-hook)
|
12
|
+
- [Setting Up a Liveness Probe](#setting-up-a-liveness-probe)
|
13
|
+
8. [Useful Links](#useful-links)
|
14
|
+
|
15
|
+
## GVCs vs. Orgs
|
16
|
+
|
17
|
+
- A "GVC" roughly corresponds to a Heroku "app."
|
18
|
+
- Images are available at the org level.
|
19
|
+
- Multiple GVCs within an org can use the same image.
|
20
|
+
- You can have different images within a GVC and even within a workload. This flexibility is one of the key differences
|
21
|
+
compared to Heroku apps.
|
22
|
+
|
23
|
+
## RAM
|
24
|
+
|
25
|
+
Any workload replica that reaches the max memory is terminated and restarted. You can configure alerts for workload
|
26
|
+
restarts and the percentage of memory used in the Control Plane UX.
|
27
|
+
|
28
|
+
Here are the steps for configuring an alert for the percentage of memory used:
|
29
|
+
|
30
|
+
1. Navigate to the workload that you want to configure the alert for
|
31
|
+
2. Click "Metrics" on the left menu to go to Grafana
|
32
|
+
3. On Grafana, go to the alerting page by clicking on the alert icon in the sidebar
|
33
|
+
4. Click on "New alert rule"
|
34
|
+
5. In the "Set a query and alert condition" section, select "Grafana managed alert"
|
35
|
+
6. There should be a default query named `A`
|
36
|
+
7. Change the data source of the query to `metrics`
|
37
|
+
8. Click "Code" on the top right of the query and enter `mem_used{workload="workload_name"} / mem_reserved{workload="workload_name"} * 100`
|
38
|
+
(replace `workload_name` with the name of the workload)
|
39
|
+
9. There should be a default expression named `B`, with the type `Reduce`, the function `Last`, and the input `A` (this
|
40
|
+
ensures that we're getting the last data point of the query)
|
41
|
+
10. There should be a default expression named `C`, with the type `Threshold`, and the input `B` (this is where you
|
42
|
+
configure the condition for firing the alert, e.g., `IS ABOVE 95`)
|
43
|
+
11. You can then preview the alert and check if it's firing or not based on the example time range of the query
|
44
|
+
12. In the "Alert evaluation behavior" section, you can configure how often the alert should be evaluated and for how
|
45
|
+
long the condition should be true before firing (for example, you might want the alert only to be fired if the
|
46
|
+
percentage has been above `95` for more than 20 seconds)
|
47
|
+
13. In the "Add details for your alert" section, fill out the name, folder, group, and summary for your alert
|
48
|
+
14. In the "Notifications" section, you can configure a label for the alert if you're using a custom notification policy,
|
49
|
+
but there should be a default root route for all alerts
|
50
|
+
15. Once you're done, save and exit in the top right of the page
|
51
|
+
16. Click "Contact points" on the top menu
|
52
|
+
17. Edit the `grafana-default-email` contact point and add the email where you want to receive notifications
|
53
|
+
18. You should now receive notifications for the alert in your email
|
54
|
+
|
55
|
+

|
56
|
+
|
57
|
+
The steps for configuring an alert for workload restarts are almost identical, but the code for the query would be
|
58
|
+
`container_restarts`.
|
59
|
+
|
60
|
+
For more information on Grafana alerts, see: https://grafana.com/docs/grafana/latest/alerting/
|
61
|
+
|
62
|
+
## Remote IP
|
63
|
+
|
64
|
+
The actual remote IP of the workload container is in the 127.0.0.x network, so that will be the value of the
|
65
|
+
`REMOTE_ADDR` env var.
|
66
|
+
|
67
|
+
However, Control Plane additionally sets the `x-forwarded-for` and `x-envoy-external-address` headers (and others - see:
|
68
|
+
https://docs.controlplane.com/concepts/security#headers). On Rails, the `ActionDispatch::RemoteIp` middleware should
|
69
|
+
pick those up and automatically populate `request.remote_ip`.
|
70
|
+
|
71
|
+
So `REMOTE_ADDR` should not be used directly, only `request.remote_ip`.
|
72
|
+
|
73
|
+
## ENV Values
|
74
|
+
|
75
|
+
You can store ENV values used by a container (within a workload) within Control Plane at the following levels:
|
76
|
+
|
77
|
+
1. Workload Container
|
78
|
+
2. GVC
|
79
|
+
|
80
|
+
For your "review apps," it is convenient to have simple ENVs stored in plain text in your source code. You will want to
|
81
|
+
keep some ENVs, like the Rails' `SECRET_KEY_BASE`, out of your source code. For staging and production apps, you will
|
82
|
+
set these values directly at the GVC or workload levels, so none of these ENV values are committed to the source code.
|
83
|
+
|
84
|
+
For storing ENVs in the source code, we can use a level of indirection so that you can store an ENV value in your source
|
85
|
+
code like `cpln://secret/my-app-review-env-secrets.SECRET_KEY_BASE` and then have the secret value stored at the org
|
86
|
+
level, which applies to your GVCs mapped to that org.
|
87
|
+
|
88
|
+
Here is how you do this:
|
89
|
+
|
90
|
+
1. In the upper left "Manage Org" menu, click on "Secrets"
|
91
|
+
2. Create a secret with `Secret Type: Dictionary` (e.g., `my-secrets`) and add the secret env vars there
|
92
|
+
3. In the upper left "Manage GVC" menu, click on "Identities"
|
93
|
+
4. Create an identity (e.g., `my-identity`)
|
94
|
+
5. Navigate to the workload that you want to associate with the identity created
|
95
|
+
6. Click "Identity" on the left menu and select the identity created
|
96
|
+
7. In the lower left "Access Control" menu, click on "Policies"
|
97
|
+
8. Create a policy with `Target Kind: Secret` and add a binding with the `reveal` permission for the identity created
|
98
|
+
9. Use `cpln://secret/...` in the app to access the secret env vars (e.g., `cpln://secret/my-secrets.SOME_VAR`)
|
99
|
+
|
100
|
+
## CI
|
101
|
+
|
102
|
+
**Note:** Docker builds much slower on Apple Silicon, so try configuring CI to build the images when using Apple
|
103
|
+
hardware.
|
104
|
+
|
105
|
+
Make sure to create a profile on CI before running any `cpln` or `cpl` commands.
|
106
|
+
|
107
|
+
```sh
|
108
|
+
CPLN_TOKEN=...
|
109
|
+
cpln profile create default --token ${CPLN_TOKEN}
|
110
|
+
```
|
111
|
+
|
112
|
+
Also, log in to the Control Plane Docker repository if building and pushing an image.
|
113
|
+
|
114
|
+
```sh
|
115
|
+
cpln image docker-login
|
116
|
+
```
|
117
|
+
|
118
|
+
## Memcached
|
119
|
+
|
120
|
+
On the workload container for Memcached (using the `memcached:alpine` image), configure the command with the args
|
121
|
+
`-l 0.0.0.0`.
|
122
|
+
|
123
|
+
To do this:
|
124
|
+
|
125
|
+
1. Navigate to the workload container for Memcached
|
126
|
+
2. Click "Command" on the top menu
|
127
|
+
3. Add the args and save
|
128
|
+
|
129
|
+

|
130
|
+
|
131
|
+
## Sidekiq
|
132
|
+
|
133
|
+
### Quieting Non-Critical Workers During Deployments
|
134
|
+
|
135
|
+
To avoid locks in migrations, we can quiet non-critical workers during deployments. Doing this early enough in the CI
|
136
|
+
allows all workers to finish jobs gracefully before deploying the new image.
|
137
|
+
|
138
|
+
There's no need to unquiet the workers, as that will happen automatically after deploying the new image.
|
139
|
+
|
140
|
+
```sh
|
141
|
+
cpl run 'rails runner "Sidekiq::ProcessSet.new.each { |w| w.quiet! unless w[%q(hostname)].start_with?(%q(criticalworker.)) }"' -a my-app
|
142
|
+
```
|
143
|
+
|
144
|
+
### Setting Up a Pre Stop Hook
|
145
|
+
|
146
|
+
By setting up a pre stop hook in the lifecycle of the workload container for Sidekiq, which sends "QUIET" to the workers,
|
147
|
+
we can ensure that all workers will finish jobs gracefully before Control Plane stops the replica. That also works
|
148
|
+
nicely for multiple replicas.
|
149
|
+
|
150
|
+
A couple of notes:
|
151
|
+
|
152
|
+
- We can't use the process name as regex because it's Ruby, not Sidekiq.
|
153
|
+
- We need to add a space after `sidekiq`; otherwise, it sends `TSTP` to the `sidekiqswarm` process as well, and for some
|
154
|
+
reason, that doesn't work.
|
155
|
+
|
156
|
+
So with `^` and `\s`, we guarantee it's sent only to worker processes.
|
157
|
+
|
158
|
+
```sh
|
159
|
+
pkill -TSTP -f ^sidekiq\s
|
160
|
+
```
|
161
|
+
|
162
|
+
To do this:
|
163
|
+
|
164
|
+
1. Navigate to the workload container for Sidekiq
|
165
|
+
2. Click "Lifecycle" on the top menu
|
166
|
+
3. Add the command and args below "Pre Stop Hook" and save
|
167
|
+
|
168
|
+

|
169
|
+
|
170
|
+
### Setting Up a Liveness Probe
|
171
|
+
|
172
|
+
To set up a liveness probe on port 7433, see: https://github.com/arturictus/sidekiq_alive
|
173
|
+
|
174
|
+
## Useful Links
|
175
|
+
|
176
|
+
- For best practices for the app's Dockerfile, see: https://lipanski.com/posts/dockerfile-ruby-best-practices
|
177
|
+
- For migrating from Heroku Postgres to RDS, see: https://pelle.io/posts/hetzner-rds-postgres
|
data/examples/circleci.yml
CHANGED
@@ -8,8 +8,8 @@ build-staging:
|
|
8
8
|
- image: cimg/ruby:3.1-node
|
9
9
|
resource_class: large
|
10
10
|
environment:
|
11
|
-
CPLN_ORG:
|
12
|
-
APP_NAME:
|
11
|
+
CPLN_ORG: my-org
|
12
|
+
APP_NAME: my-app-staging
|
13
13
|
steps:
|
14
14
|
- checkout
|
15
15
|
- setup_remote_docker:
|
@@ -21,14 +21,13 @@ build-staging:
|
|
21
21
|
cpln profile create default --token ${CPLN_TOKEN} --org ${CPLN_ORG} --gvc ${APP_NAME}
|
22
22
|
cpln image docker-login
|
23
23
|
|
24
|
-
|
25
|
-
sudo ln -s ~/heroku-to-control-plane/cpl /usr/local/bin/cpl
|
24
|
+
gem install cpl
|
26
25
|
- run:
|
27
26
|
name: Containerize and push image
|
28
27
|
command: cpl build-image -a ${APP_NAME}
|
29
28
|
- run:
|
30
29
|
name: Database tasks
|
31
|
-
command: cpl run:detached
|
30
|
+
command: cpl run:detached -a ${APP_NAME} --image latest -- rails db:migrate
|
32
31
|
- run:
|
33
32
|
name: Deploy image
|
34
33
|
command: cpl deploy-image -a ${APP_NAME}
|
@@ -43,7 +42,7 @@ build-review-app:
|
|
43
42
|
- image: cimg/ruby:3.1-node
|
44
43
|
resource_class: large
|
45
44
|
environment:
|
46
|
-
CPLN_ORG: my-org
|
45
|
+
CPLN_ORG: my-org
|
47
46
|
steps:
|
48
47
|
- checkout
|
49
48
|
- setup_remote_docker:
|
@@ -65,7 +64,7 @@ build-review-app:
|
|
65
64
|
- run:
|
66
65
|
name: Provision review app if needed
|
67
66
|
command: |
|
68
|
-
if ! cpl
|
67
|
+
if ! cpl exists -a ${APP_NAME}; then
|
69
68
|
cpl setup-app -a ${APP_NAME}
|
70
69
|
echo "export NEW_APP=true" >> $BASH_ENV
|
71
70
|
fi
|
@@ -77,9 +76,9 @@ build-review-app:
|
|
77
76
|
name: Database tasks
|
78
77
|
command: |
|
79
78
|
if [ -n "${NEW_APP}" ]; then
|
80
|
-
cpl run:detached
|
79
|
+
cpl run:detached -a ${APP_NAME} --image latest -- LOG_LEVEL=warn rails db:reset
|
81
80
|
else
|
82
|
-
cpl run:detached
|
81
|
+
cpl run:detached -a ${APP_NAME} --image latest -- LOG_LEVEL=warn rails db:migrate
|
83
82
|
fi
|
84
83
|
- run:
|
85
84
|
name: Deploy image
|
data/examples/controlplane.yml
CHANGED
@@ -1,47 +1,49 @@
|
|
1
|
+
# Keys beginning with "cpln_" correspond to your settings in Control Plane.
|
2
|
+
|
1
3
|
aliases:
|
2
4
|
common: &common
|
3
|
-
#
|
4
|
-
# Production apps will use a different
|
5
|
-
# keys beginning with CPLN correspond to your settings in Control Plane
|
5
|
+
# Organization name for staging (customize to your needs).
|
6
|
+
# Production apps will use a different organization, specified below, for security.
|
6
7
|
cpln_org: my-org-staging
|
7
8
|
|
8
|
-
# Example apps use only location.
|
9
|
-
# TODO
|
9
|
+
# Example apps use only one location. Control Plane offers the ability to use multiple locations.
|
10
|
+
# TODO: Allow specification of multiple locations.
|
10
11
|
default_location: aws-us-east-2
|
11
12
|
|
12
13
|
# Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
|
13
14
|
one_off_workload: rails
|
14
15
|
|
15
|
-
# Workloads that are application itself and are using application
|
16
|
+
# Workloads that are for the application itself and are using application Docker images.
|
16
17
|
app_workloads:
|
17
18
|
- rails
|
18
19
|
- sidekiq
|
19
20
|
|
20
|
-
# Additional "service type" workloads, using non-application
|
21
|
+
# Additional "service type" workloads, using non-application Docker images.
|
21
22
|
additional_workloads:
|
22
23
|
- redis
|
23
24
|
- postgres
|
24
25
|
- memcached
|
25
26
|
|
26
|
-
# Configure the workload name used when maintenance mode is on (defaults to
|
27
|
+
# Configure the workload name used when maintenance mode is on (defaults to "maintenance")
|
27
28
|
maintenance_workload: maintenance
|
28
29
|
|
29
30
|
apps:
|
30
31
|
my-app-staging:
|
31
|
-
# Use the values from the common section above
|
32
|
+
# Use the values from the common section above.
|
32
33
|
<<: *common
|
33
34
|
my-app-review:
|
34
35
|
<<: *common
|
35
|
-
#
|
36
|
-
#
|
36
|
+
# If `match_if_app_name_starts_with` is `true`, then use this config for app names starting with this name,
|
37
|
+
# e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
|
37
38
|
match_if_app_name_starts_with: true
|
38
39
|
my-app-production:
|
39
40
|
<<: *common
|
40
|
-
# Use a different
|
41
|
+
# Use a different organization for production.
|
41
42
|
cpln_org: my-org-production
|
42
|
-
# Allows running command
|
43
|
+
# Allows running the command `cpl promote-app-from-upstream -a my-app-production`
|
44
|
+
# to promote the staging app to production.
|
43
45
|
upstream: my-app-staging
|
44
46
|
my-app-other:
|
45
47
|
<<: *common
|
46
|
-
#
|
48
|
+
# You can specify a different `Dockerfile` relative to the `.controlplane/` directory (defaults to "Dockerfile").
|
47
49
|
dockerfile: ../some_other/Dockerfile
|
data/lib/command/base.rb
CHANGED
@@ -210,7 +210,7 @@ module Command
|
|
210
210
|
|
211
211
|
# Or special string to indicate no image available
|
212
212
|
if matching_items.empty?
|
213
|
-
"#{app_name}:#{NO_IMAGE_AVAILABLE}"
|
213
|
+
name_only ? "#{app_name}:#{NO_IMAGE_AVAILABLE}" : nil
|
214
214
|
else
|
215
215
|
latest_item = matching_items.max_by { |item| extract_image_number(item["name"]) }
|
216
216
|
name_only ? latest_item["name"] : latest_item
|
@@ -51,6 +51,7 @@ module Command
|
|
51
51
|
|
52
52
|
images = cp.image_query(app_name)["items"].filter { |item| item["name"].start_with?("#{app_name}:") }
|
53
53
|
image = latest_image_from(images, app_name: app_name, name_only: false)
|
54
|
+
next unless image
|
54
55
|
|
55
56
|
created_date = DateTime.parse(image["created"])
|
56
57
|
diff_in_days = (now - created_date).to_i
|
data/lib/cpl/version.rb
CHANGED
data/lib/cpl.rb
CHANGED
@@ -40,16 +40,57 @@ end
|
|
40
40
|
module Cpl
|
41
41
|
class Error < StandardError; end
|
42
42
|
|
43
|
-
class Cli < Thor
|
43
|
+
class Cli < Thor # rubocop:disable Metrics/ClassLength
|
44
44
|
package_name "cpl"
|
45
45
|
default_task :no_command
|
46
46
|
|
47
47
|
def self.start(*args)
|
48
|
+
check_cpln_version
|
49
|
+
check_cpl_version
|
48
50
|
fix_help_option
|
49
51
|
|
50
52
|
super(*args)
|
51
53
|
end
|
52
54
|
|
55
|
+
def self.check_cpln_version # rubocop:disable Metrics/MethodLength
|
56
|
+
return if @checked_cpln_version
|
57
|
+
|
58
|
+
@checked_cpln_version = true
|
59
|
+
|
60
|
+
result = `cpln --version 2>/dev/null`
|
61
|
+
if $CHILD_STATUS.success?
|
62
|
+
data = JSON.parse(result)
|
63
|
+
|
64
|
+
version = data["npm"]
|
65
|
+
min_version = Cpl::MIN_CPLN_VERSION
|
66
|
+
if Gem::Version.new(version) < Gem::Version.new(min_version)
|
67
|
+
::Shell.abort("Current 'cpln' version: #{version}. Minimum supported version: #{min_version}. " \
|
68
|
+
"Please update it with 'npm update -g @controlplane/cli'.")
|
69
|
+
end
|
70
|
+
else
|
71
|
+
::Shell.abort("Can't find 'cpln' executable. Please install it with 'npm install -g @controlplane/cli'.")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.check_cpl_version # rubocop:disable Metrics/MethodLength
|
76
|
+
return if @checked_cpl_version
|
77
|
+
|
78
|
+
@checked_cpl_version = true
|
79
|
+
|
80
|
+
result = `gem search ^cpl$ --remote 2>/dev/null`
|
81
|
+
return unless $CHILD_STATUS.success?
|
82
|
+
|
83
|
+
matches = result.match(/cpl \((.+)\)/)
|
84
|
+
return unless matches
|
85
|
+
|
86
|
+
version = Cpl::VERSION
|
87
|
+
latest_version = matches[1]
|
88
|
+
return unless Gem::Version.new(version) < Gem::Version.new(latest_version)
|
89
|
+
|
90
|
+
::Shell.warn("You are not using the latest 'cpl' version. Please update it with 'gem update cpl'.")
|
91
|
+
$stderr.puts
|
92
|
+
end
|
93
|
+
|
53
94
|
# This is so that we're able to run `cpl COMMAND --help` to print the help
|
54
95
|
# (it basically changes it to `cpl --help COMMAND`, which Thor recognizes)
|
55
96
|
# Based on https://stackoverflow.com/questions/49042591/how-to-add-help-h-flag-to-thor-command
|
data/script/update_command_docs
CHANGED
@@ -46,7 +46,7 @@ file_data =
|
|
46
46
|
<<~DATA
|
47
47
|
<!-- NOTE: This file is automatically generated by running `script/generate_commands_docs`. Do NOT edit it manually. -->
|
48
48
|
|
49
|
-
|
49
|
+
## Common Options
|
50
50
|
|
51
51
|
```
|
52
52
|
-a XXX, --app XXX app ref on Control Plane (GVC)
|
@@ -55,7 +55,7 @@ file_data =
|
|
55
55
|
This `-a` option is used in most of the commands and will pick all other app configurations from the project-specific
|
56
56
|
`.controlplane/controlplane.yml` file.
|
57
57
|
|
58
|
-
|
58
|
+
## Commands
|
59
59
|
|
60
60
|
#{commands_str}
|
61
61
|
DATA
|
data/templates/daily-task.yml
CHANGED
@@ -4,23 +4,24 @@ spec:
|
|
4
4
|
# https://docs.controlplane.com/reference/workload#cron-configuration
|
5
5
|
type: cron
|
6
6
|
job:
|
7
|
-
# Run daily job at 2am
|
7
|
+
# Run daily job at 2am (see cron docs)
|
8
8
|
schedule: 0 2 * * *
|
9
9
|
# Never or OnFailure
|
10
10
|
restartPolicy: Never
|
11
11
|
containers:
|
12
12
|
- name: daily-task
|
13
|
+
cpu: 50m
|
14
|
+
memory: 256Mi
|
13
15
|
args:
|
14
16
|
- bundle
|
15
17
|
- exec
|
16
18
|
- rails
|
17
19
|
- db:prepare
|
18
|
-
cpu: 50m
|
19
20
|
inheritEnv: true
|
20
|
-
image:
|
21
|
-
memory: 256Mi
|
21
|
+
image: "/org/APP_ORG/image/APP_IMAGE"
|
22
22
|
defaultOptions:
|
23
23
|
autoscaling:
|
24
|
+
minScale: 1
|
24
25
|
maxScale: 1
|
25
26
|
capacityAI: false
|
26
27
|
firewallConfig:
|
data/templates/maintenance.yml
CHANGED
@@ -6,15 +6,16 @@ spec:
|
|
6
6
|
- name: maintenance
|
7
7
|
env:
|
8
8
|
- name: PORT
|
9
|
-
value:
|
9
|
+
value: "3000"
|
10
10
|
- name: PAGE_URL
|
11
|
-
value:
|
12
|
-
image:
|
11
|
+
value: ""
|
12
|
+
image: "shakacode/maintenance-mode"
|
13
13
|
ports:
|
14
14
|
- number: 3000
|
15
15
|
protocol: http
|
16
16
|
defaultOptions:
|
17
17
|
autoscaling:
|
18
|
+
minScale: 1
|
18
19
|
maxScale: 1
|
19
20
|
capacityAI: false
|
20
21
|
timeoutSeconds: 60
|
data/templates/memcached.yml
CHANGED
@@ -7,15 +7,16 @@ spec:
|
|
7
7
|
cpu: 3m
|
8
8
|
memory: 10Mi
|
9
9
|
args:
|
10
|
-
-
|
10
|
+
- "-l"
|
11
11
|
- 0.0.0.0
|
12
|
-
image:
|
12
|
+
image: "memcached:alpine"
|
13
13
|
ports:
|
14
14
|
- number: 11211
|
15
15
|
protocol: tcp
|
16
16
|
defaultOptions:
|
17
17
|
autoscaling:
|
18
18
|
metric: latency
|
19
|
+
minScale: 1
|
19
20
|
maxScale: 1
|
20
21
|
capacityAI: false
|
21
22
|
firewallConfig:
|
data/templates/postgres.yml
CHANGED
@@ -13,17 +13,18 @@ spec:
|
|
13
13
|
value: password123
|
14
14
|
- name: POSTGRES_USER
|
15
15
|
value: postgres
|
16
|
-
image:
|
16
|
+
image: "postgres:13.8-alpine"
|
17
17
|
ports:
|
18
18
|
- number: 5432
|
19
19
|
protocol: tcp
|
20
20
|
volumes:
|
21
21
|
- path: /var/lib/postgresql/data
|
22
22
|
recoveryPolicy: retain
|
23
|
-
uri:
|
23
|
+
uri: "scratch://postgres-vol"
|
24
24
|
defaultOptions:
|
25
25
|
autoscaling:
|
26
26
|
metric: latency
|
27
|
+
minScale: 1
|
27
28
|
maxScale: 1
|
28
29
|
capacityAI: false
|
29
30
|
firewallConfig:
|
data/templates/rails.yml
CHANGED
@@ -5,14 +5,15 @@ spec:
|
|
5
5
|
containers:
|
6
6
|
- name: rails
|
7
7
|
cpu: 512m
|
8
|
-
inheritEnv: true
|
9
|
-
image: '/org/APP_ORG/image/APP_IMAGE'
|
10
8
|
memory: 1Gi
|
9
|
+
inheritEnv: true
|
10
|
+
image: "/org/APP_ORG/image/APP_IMAGE"
|
11
11
|
ports:
|
12
12
|
- number: 3000
|
13
13
|
protocol: http
|
14
14
|
defaultOptions:
|
15
15
|
autoscaling:
|
16
|
+
minScale: 1
|
16
17
|
maxScale: 1
|
17
18
|
capacityAI: false
|
18
19
|
timeoutSeconds: 60
|
data/templates/redis.yml
CHANGED
@@ -6,13 +6,14 @@ spec:
|
|
6
6
|
- name: redis
|
7
7
|
cpu: 3m
|
8
8
|
memory: 20Mi
|
9
|
-
image:
|
9
|
+
image: "redis:latest"
|
10
10
|
ports:
|
11
11
|
- number: 6379
|
12
12
|
protocol: tcp
|
13
13
|
defaultOptions:
|
14
14
|
autoscaling:
|
15
15
|
metric: latency
|
16
|
+
minScale: 1
|
16
17
|
maxScale: 1
|
17
18
|
capacityAI: false
|
18
19
|
firewallConfig:
|
data/templates/sidekiq.yml
CHANGED
@@ -4,21 +4,30 @@ spec:
|
|
4
4
|
type: standard
|
5
5
|
containers:
|
6
6
|
- name: sidekiq
|
7
|
+
cpu: 50m
|
8
|
+
memory: 256Mi
|
7
9
|
args:
|
8
10
|
- bundle
|
9
11
|
- exec
|
10
12
|
- sidekiq
|
11
|
-
-
|
13
|
+
- "-C"
|
12
14
|
- config/sidekiq.yml
|
13
|
-
cpu: 50m
|
14
15
|
inheritEnv: true
|
15
|
-
image:
|
16
|
-
memory: 256Mi
|
16
|
+
image: "/org/APP_ORG/image/APP_IMAGE"
|
17
17
|
ports:
|
18
18
|
- number: 7433
|
19
19
|
protocol: http
|
20
|
+
lifecycle:
|
21
|
+
preStop:
|
22
|
+
exec:
|
23
|
+
command:
|
24
|
+
- pkill
|
25
|
+
- "-TSTP"
|
26
|
+
- "-f"
|
27
|
+
- ^sidekiq\s
|
20
28
|
defaultOptions:
|
21
29
|
autoscaling:
|
30
|
+
minScale: 1
|
22
31
|
maxScale: 1
|
23
32
|
capacityAI: false
|
24
33
|
firewallConfig:
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cpl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Gordon
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-06-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: debug
|
@@ -219,9 +219,13 @@ files:
|
|
219
219
|
- bin/cpl
|
220
220
|
- cpl
|
221
221
|
- cpl.gemspec
|
222
|
+
- docs/assets/grafana-alert.png
|
223
|
+
- docs/assets/memcached.png
|
224
|
+
- docs/assets/sidekiq-pre-stop-hook.png
|
222
225
|
- docs/commands.md
|
223
226
|
- docs/postgres.md
|
224
227
|
- docs/redis.md
|
228
|
+
- docs/tips.md
|
225
229
|
- docs/troubleshooting.md
|
226
230
|
- examples/circleci.yml
|
227
231
|
- examples/controlplane.yml
|