cpl 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem](https://badge.fury.io/rb/cpl.svg)](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
|
+
![](assets/grafana-alert.png)
|
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
|
+
![](assets/memcached.png)
|
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
|
+
![](assets/sidekiq-pre-stop-hook.png)
|
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
|