cpl 2.0.0.rc.1 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -3
- data/Gemfile.lock +2 -2
- data/docs/commands.md +3 -1
- data/docs/redis.md +25 -9
- data/lib/command/cleanup_stale_apps.rb +8 -18
- data/lib/command/delete.rb +29 -9
- data/lib/core/controlplane.rb +19 -0
- data/lib/core/controlplane_api.rb +4 -0
- data/lib/cpl/version.rb +2 -2
- data/lib/cpl.rb +18 -10
- data/templates/memcached.yml +3 -3
- data/templates/postgres.yml +1 -1
- data/templates/redis.yml +3 -3
- data/templates/redis2.yml +37 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7601f22a541072ea22c5745496d77ee63409d8975903f14582e2681963e9e0ff
|
4
|
+
data.tar.gz: e3a189dbb1506571133924f9640bd144c6c1a7d1a7233096b9fbd13bef8b0a82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0e2603b1e9d29e2f23deb2620edb94a51e13763a48985064facfd9ce2f9a61731267176766ad037e826430283c253300334e35514c9de60a5cda59a97c8b81a
|
7
|
+
data.tar.gz: 8c97ac2b7d5f349d90a41bf1acb8dea6e72d107cb275361792547ca9faa4b1bca66bc2566558a05fb336e1bee39d577c9c5cc0e3602971037cd2d44d5f975ed8
|
data/CHANGELOG.md
CHANGED
@@ -14,14 +14,23 @@ Changes since the last non-beta release.
|
|
14
14
|
|
15
15
|
_Please add entries here for your pull requests that are not yet released._
|
16
16
|
|
17
|
-
|
17
|
+
### Fixed
|
18
|
+
|
19
|
+
- Fixed issue where `cleanup-stale-apps` command fails to delete apps with volumesets. [PR 175](https://github.com/shakacode/heroku-to-control-plane/pull/175) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
20
|
+
|
21
|
+
## [2.0.0] - 2024-05-14
|
18
22
|
|
19
23
|
### BREAKING CHANGES
|
20
24
|
|
21
25
|
- Commands that finished with a failure now exit with code `64` instead of `1`. [PR 132](https://github.com/shakacode/heroku-to-control-plane/pull/132) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
26
|
+
- Bumped minimum `cpln` version to `2.0.1` (`cpln workload cron get` is required). [PR 171](https://github.com/shakacode/heroku-to-control-plane/pull/171) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
22
27
|
- `run:cleanup` command has been removed. [PR 151](https://github.com/shakacode/heroku-to-control-plane/pull/151) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
23
28
|
- `deploy-image` command now runs the release script in the context of the `run` command. [PR 151](https://github.com/shakacode/heroku-to-control-plane/pull/151) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
24
29
|
|
30
|
+
### Fixed
|
31
|
+
|
32
|
+
- Fixed race conditions when using latest image in `run` command. [PR 163](https://github.com/shakacode/heroku-to-control-plane/pull/163) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
33
|
+
|
25
34
|
### Added
|
26
35
|
|
27
36
|
- Added options to `run` command to override the workload container's `--cpu`, `--memory`, and `--entrypoint`. [PR 151](https://github.com/shakacode/heroku-to-control-plane/pull/151) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
@@ -32,9 +41,12 @@ _Please add entries here for your pull requests that are not yet released._
|
|
32
41
|
|
33
42
|
### Changed
|
34
43
|
|
44
|
+
- An error is now raised if the org does not exist. [PR 167](https://github.com/shakacode/heroku-to-control-plane/pull/167) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
45
|
+
- Common options are now shown in help. [PR 169](https://github.com/shakacode/heroku-to-control-plane/pull/169) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
35
46
|
- `run` command now uses a single reusable cron workload and works for both interactive and non-interactive jobs. [PR 151](https://github.com/shakacode/heroku-to-control-plane/pull/151) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
36
47
|
- `run:detached` command has been deprecated in favor of `run`. [PR 151](https://github.com/shakacode/heroku-to-control-plane/pull/151) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
37
48
|
- `deploy-image` command now raises an error if image does not exist. [PR 153](https://github.com/shakacode/heroku-to-control-plane/pull/153) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
49
|
+
- `delete` command now unbinds identity from policy (if bound) when deleting app. [PR 170](https://github.com/shakacode/heroku-to-control-plane/pull/170) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
|
38
50
|
|
39
51
|
## [1.4.0] - 2024-03-20
|
40
52
|
|
@@ -178,8 +190,8 @@ _Please add entries here for your pull requests that are not yet released._
|
|
178
190
|
|
179
191
|
- Initial release
|
180
192
|
|
181
|
-
[Unreleased]: https://github.com/shakacode/heroku-to-control-plane/compare/v2.0.0
|
182
|
-
[2.0.0
|
193
|
+
[Unreleased]: https://github.com/shakacode/heroku-to-control-plane/compare/v2.0.0...HEAD
|
194
|
+
[2.0.0]: https://github.com/shakacode/heroku-to-control-plane/compare/v1.4.0...v2.0.0
|
183
195
|
[1.4.0]: https://github.com/shakacode/heroku-to-control-plane/compare/v1.3.0...v1.4.0
|
184
196
|
[1.3.0]: https://github.com/shakacode/heroku-to-control-plane/compare/v1.2.0...v1.3.0
|
185
197
|
[1.2.0]: https://github.com/shakacode/heroku-to-control-plane/compare/v1.1.2...v1.2.0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cpl (2.0.
|
4
|
+
cpl (2.0.1)
|
5
5
|
debug (~> 1.7.1)
|
6
6
|
dotenv (~> 2.8.1)
|
7
7
|
jwt (~> 2.8.1)
|
@@ -52,7 +52,7 @@ GEM
|
|
52
52
|
rdoc (6.6.3.1)
|
53
53
|
psych (>= 4.0.0)
|
54
54
|
regexp_parser (2.9.0)
|
55
|
-
reline (0.5.
|
55
|
+
reline (0.5.7)
|
56
56
|
io-console (~> 0.5)
|
57
57
|
rexml (3.2.6)
|
58
58
|
rspec (3.12.0)
|
data/docs/commands.md
CHANGED
@@ -66,7 +66,8 @@ cpl cleanup-images -a $APP_NAME
|
|
66
66
|
|
67
67
|
### `cleanup-stale-apps`
|
68
68
|
|
69
|
-
- Deletes the whole app (GVC with all workloads and all images) for all stale apps
|
69
|
+
- Deletes the whole app (GVC with all workloads, all volumesets and all images) for all stale apps
|
70
|
+
- Also unbinds the app from the secrets policy, as long as both the identity and the policy exist (and are bound)
|
70
71
|
- Stale apps are identified based on the creation date of the latest image
|
71
72
|
- Specify the amount of days after an app should be considered stale through `stale_app_image_deployed_days` in the `.controlplane/controlplane.yml` file
|
72
73
|
- If `match_if_app_name_starts_with` is `true` in the `.controlplane/controlplane.yml` file, it will delete all stale apps that start with the name
|
@@ -106,6 +107,7 @@ cpl copy-image-from-upstream -a $APP_NAME --upstream-token $UPSTREAM_TOKEN --ima
|
|
106
107
|
### `delete`
|
107
108
|
|
108
109
|
- Deletes the whole app (GVC with all workloads, all volumesets and all images) or a specific workload
|
110
|
+
- Also unbinds the app from the secrets policy, as long as both the identity and the policy exist (and are bound)
|
109
111
|
- Will ask for explicit user confirmation
|
110
112
|
|
111
113
|
```sh
|
data/docs/redis.md
CHANGED
@@ -1,15 +1,31 @@
|
|
1
|
-
# Migrating Redis
|
1
|
+
# Migrating Redis databases
|
2
2
|
|
3
|
-
|
3
|
+
There are two templates examples in this repo:
|
4
|
+
- `redis` - basic non-persistent template. It is good for review-apps or staging or where no persistence is required
|
5
|
+
- `redis2` - basic persistent template. Good for production where persistence is needed, but cluster is overkill.
|
6
|
+
|
7
|
+
## Option 1: use SLAVEOF (easier way)
|
8
|
+
|
9
|
+
1. create a redis workload that will accept data
|
10
|
+
2. execute `SLAVEOF source_host source_port`, if needed use `masterauth` to provide auth details
|
11
|
+
3. wait for replication to pick up all changes (usually quickly), use `INFO` or `DBSIZE` to check progress
|
12
|
+
4. stop app completely and ensure nothing is writing to any of redises
|
13
|
+
5. execute `SLAVEOF no one` to disconnect replication
|
14
|
+
6. switch `REDIS_URL` in the app to point to new server
|
15
|
+
7. start the app
|
16
|
+
|
17
|
+
## Option 2: use Redis-RIOT (harder way, where option 1 is not possible)
|
18
|
+
|
19
|
+
### General considerations:
|
4
20
|
|
5
21
|
1. Heroku uses self-signed TLS certificates, which are not verifiable. It needs special handling by setting
|
6
|
-
|
22
|
+
The tool that satisfies those criteria is [Redis-RIOT](https://developer.redis.com/riot/riot-redis/index.html)
|
7
23
|
|
8
24
|
2. We are moving to private Redis that don't have a public URL, so have to do it from a Control Plane GVC container.
|
9
25
|
|
10
26
|
The tool that satisfies those criteria is [Redis-RIOT](https://developer.redis.com/riot/riot-redis/index.html)
|
11
27
|
|
12
|
-
|
28
|
+
### Heroku Redis:
|
13
29
|
|
14
30
|
As Redis-RIOT says, master redis should have keyspace-notifications set to `KA` to be able to do live replication.
|
15
31
|
To do that:
|
@@ -23,7 +39,7 @@ Connect to heroku Redis CLI:
|
|
23
39
|
heroku redis:cli -a my-app
|
24
40
|
```
|
25
41
|
|
26
|
-
|
42
|
+
### Control Plane Redis:
|
27
43
|
|
28
44
|
Connect to Control Plane Redis CLI:
|
29
45
|
|
@@ -36,10 +52,10 @@ apt-get update
|
|
36
52
|
apt-get install redis -y
|
37
53
|
|
38
54
|
# connect to local cloud Redis
|
39
|
-
redis-cli -u MY_CONTROL_PLANE_REDIS_URL
|
55
|
+
redis-cli -u MY_CONTROL_PLANE_REDIS_URL -p 6379
|
40
56
|
```
|
41
57
|
|
42
|
-
|
58
|
+
### Useful Redis CLI commands:
|
43
59
|
|
44
60
|
Quick-check keys qty:
|
45
61
|
```
|
@@ -49,7 +65,7 @@ info keyspace
|
|
49
65
|
db0:keys=9496,expires=2941,avg_ttl=77670114535
|
50
66
|
```
|
51
67
|
|
52
|
-
|
68
|
+
### Create a Control Plane sync workload
|
53
69
|
|
54
70
|
```
|
55
71
|
name: riot-redis
|
@@ -76,7 +92,7 @@ command args:
|
|
76
92
|
live
|
77
93
|
```
|
78
94
|
|
79
|
-
|
95
|
+
### Sync process
|
80
96
|
|
81
97
|
1. open 1st terminal window with heroku redis CLI, check keys qty
|
82
98
|
2. open 2nd terminal window with controlplane redis CLI, check keys qty
|
@@ -7,9 +7,10 @@ module Command
|
|
7
7
|
app_option(required: true),
|
8
8
|
skip_confirm_option
|
9
9
|
].freeze
|
10
|
-
DESCRIPTION = "Deletes the whole app (GVC with all workloads and all images) for all stale apps"
|
10
|
+
DESCRIPTION = "Deletes the whole app (GVC with all workloads, all volumesets and all images) for all stale apps"
|
11
11
|
LONG_DESCRIPTION = <<~DESC
|
12
|
-
- Deletes the whole app (GVC with all workloads and all images) for all stale apps
|
12
|
+
- Deletes the whole app (GVC with all workloads, all volumesets and all images) for all stale apps
|
13
|
+
- Also unbinds the app from the secrets policy, as long as both the identity and the policy exist (and are bound)
|
13
14
|
- Stale apps are identified based on the creation date of the latest image
|
14
15
|
- Specify the amount of days after an app should be considered stale through `stale_app_image_deployed_days` in the `.controlplane/controlplane.yml` file
|
15
16
|
- If `match_if_app_name_starts_with` is `true` in the `.controlplane/controlplane.yml` file, it will delete all stale apps that start with the name
|
@@ -28,8 +29,8 @@ module Command
|
|
28
29
|
|
29
30
|
progress.puts
|
30
31
|
stale_apps.each do |app|
|
31
|
-
|
32
|
-
|
32
|
+
delete_app(app[:name])
|
33
|
+
progress.puts
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
@@ -57,8 +58,7 @@ module Command
|
|
57
58
|
|
58
59
|
apps.push({
|
59
60
|
name: app_name,
|
60
|
-
date: created_date
|
61
|
-
images: images.map { |current_image| current_image["name"] }
|
61
|
+
date: created_date
|
62
62
|
})
|
63
63
|
end
|
64
64
|
|
@@ -72,18 +72,8 @@ module Command
|
|
72
72
|
Shell.confirm("\nAre you sure you want to delete these #{stale_apps.length} apps?")
|
73
73
|
end
|
74
74
|
|
75
|
-
def
|
76
|
-
|
77
|
-
cp.gvc_delete(app[:name])
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def delete_images(app)
|
82
|
-
app[:images].each do |image|
|
83
|
-
step("Deleting image '#{image}'") do
|
84
|
-
cp.image_delete(image)
|
85
|
-
end
|
86
|
-
end
|
75
|
+
def delete_app(app)
|
76
|
+
Cpl::Cli.start(["delete", "-a", app, "--yes"])
|
87
77
|
end
|
88
78
|
end
|
89
79
|
end
|
data/lib/command/delete.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Command
|
4
|
-
class Delete < Base
|
4
|
+
class Delete < Base # rubocop:disable Metrics/ClassLength
|
5
5
|
NAME = "delete"
|
6
6
|
OPTIONS = [
|
7
7
|
app_option(required: true),
|
@@ -11,6 +11,7 @@ module Command
|
|
11
11
|
DESCRIPTION = "Deletes the whole app (GVC with all workloads, all volumesets and all images) or a specific workload"
|
12
12
|
LONG_DESCRIPTION = <<~DESC
|
13
13
|
- Deletes the whole app (GVC with all workloads, all volumesets and all images) or a specific workload
|
14
|
+
- Also unbinds the app from the secrets policy, as long as both the identity and the policy exist (and are bound)
|
14
15
|
- Will ask for explicit user confirmation
|
15
16
|
DESC
|
16
17
|
EXAMPLES = <<~EX
|
@@ -35,7 +36,9 @@ module Command
|
|
35
36
|
private
|
36
37
|
|
37
38
|
def delete_single_workload(workload)
|
38
|
-
|
39
|
+
if cp.fetch_workload(workload).nil?
|
40
|
+
return progress.puts("Workload '#{workload}' does not exist in app '#{config.app}'.")
|
41
|
+
end
|
39
42
|
return unless confirm_delete(workload)
|
40
43
|
|
41
44
|
delete_workload(workload)
|
@@ -48,6 +51,7 @@ module Command
|
|
48
51
|
check_images
|
49
52
|
return unless confirm_delete(config.app)
|
50
53
|
|
54
|
+
unbind_identity_from_policy
|
51
55
|
delete_volumesets
|
52
56
|
delete_gvc
|
53
57
|
delete_images
|
@@ -55,9 +59,9 @@ module Command
|
|
55
59
|
|
56
60
|
def check_volumesets
|
57
61
|
@volumesets = cp.fetch_volumesets["items"]
|
58
|
-
return progress.puts("No volumesets to delete.") unless @volumesets.any?
|
62
|
+
return progress.puts("No volumesets to delete from app '#{config.app}'.") unless @volumesets.any?
|
59
63
|
|
60
|
-
message = "The following volumesets will be deleted along with the app:"
|
64
|
+
message = "The following volumesets will be deleted along with the app '#{config.app}':"
|
61
65
|
volumesets_list = @volumesets.map { |volumeset| "- #{volumeset['name']}" }.join("\n")
|
62
66
|
progress.puts("#{Shell.color(message, :red)}\n#{volumesets_list}\n\n")
|
63
67
|
end
|
@@ -65,9 +69,9 @@ module Command
|
|
65
69
|
def check_images
|
66
70
|
@images = cp.query_images["items"]
|
67
71
|
.select { |image| image["name"].start_with?("#{config.app}:") }
|
68
|
-
return progress.puts("No images to delete.") unless @images.any?
|
72
|
+
return progress.puts("No images to delete from app '#{config.app}'.") unless @images.any?
|
69
73
|
|
70
|
-
message = "The following images will be deleted along with the app:"
|
74
|
+
message = "The following images will be deleted along with the app '#{config.app}':"
|
71
75
|
images_list = @images.map { |image| "- #{image['name']}" }.join("\n")
|
72
76
|
progress.puts("#{Shell.color(message, :red)}\n#{images_list}\n\n")
|
73
77
|
end
|
@@ -89,14 +93,14 @@ module Command
|
|
89
93
|
end
|
90
94
|
|
91
95
|
def delete_workload(workload)
|
92
|
-
step("Deleting workload '#{workload}'") do
|
96
|
+
step("Deleting workload '#{workload}' from app '#{config.app}'") do
|
93
97
|
cp.delete_workload(workload)
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
97
101
|
def delete_volumesets
|
98
102
|
@volumesets.each do |volumeset|
|
99
|
-
step("Deleting volumeset '#{volumeset['name']}'") do
|
103
|
+
step("Deleting volumeset '#{volumeset['name']}' from app '#{config.app}'") do
|
100
104
|
# If the volumeset is attached to a workload, we need to delete the workload first
|
101
105
|
workload = volumeset.dig("status", "usedByWorkload")&.split("/")&.last
|
102
106
|
cp.delete_workload(workload) if workload
|
@@ -108,10 +112,26 @@ module Command
|
|
108
112
|
|
109
113
|
def delete_images
|
110
114
|
@images.each do |image|
|
111
|
-
step("Deleting image '#{image['name']}'") do
|
115
|
+
step("Deleting image '#{image['name']}' from app '#{config.app}'") do
|
112
116
|
cp.image_delete(image["name"])
|
113
117
|
end
|
114
118
|
end
|
115
119
|
end
|
120
|
+
|
121
|
+
def unbind_identity_from_policy
|
122
|
+
return if cp.fetch_identity(app_identity).nil?
|
123
|
+
|
124
|
+
policy = cp.fetch_policy(app_secrets_policy)
|
125
|
+
return if policy.nil?
|
126
|
+
|
127
|
+
is_bound = policy["bindings"].any? do |binding|
|
128
|
+
binding["principalLinks"].any? { |link| link == app_identity_link }
|
129
|
+
end
|
130
|
+
return unless is_bound
|
131
|
+
|
132
|
+
step("Unbinding identity from policy for app '#{config.app}'") do
|
133
|
+
cp.unbind_identity_from_policy(app_identity_link, app_secrets_policy)
|
134
|
+
end
|
135
|
+
end
|
116
136
|
end
|
117
137
|
end
|
data/lib/core/controlplane.rb
CHANGED
@@ -8,6 +8,8 @@ class Controlplane # rubocop:disable Metrics/ClassLength
|
|
8
8
|
@api = ControlplaneApi.new
|
9
9
|
@gvc = config.app
|
10
10
|
@org = config.org
|
11
|
+
|
12
|
+
ensure_org_exists! if org
|
11
13
|
end
|
12
14
|
|
13
15
|
# profile
|
@@ -339,6 +341,11 @@ class Controlplane # rubocop:disable Metrics/ClassLength
|
|
339
341
|
perform!(cmd)
|
340
342
|
end
|
341
343
|
|
344
|
+
def unbind_identity_from_policy(identity_link, policy)
|
345
|
+
cmd = "cpln policy remove-binding #{policy} --org #{org} --identity #{identity_link} --permission reveal"
|
346
|
+
perform!(cmd)
|
347
|
+
end
|
348
|
+
|
342
349
|
# apply
|
343
350
|
def apply_template(data) # rubocop:disable Metrics/MethodLength
|
344
351
|
Tempfile.create do |f|
|
@@ -404,6 +411,18 @@ class Controlplane # rubocop:disable Metrics/ClassLength
|
|
404
411
|
|
405
412
|
private
|
406
413
|
|
414
|
+
def org_exists?
|
415
|
+
items = api.list_orgs["items"]
|
416
|
+
items.any? { |item| item["name"] == org }
|
417
|
+
end
|
418
|
+
|
419
|
+
def ensure_org_exists!
|
420
|
+
return if org_exists?
|
421
|
+
|
422
|
+
raise "Can't find org '#{org}', please create it in the Control Plane dashboard " \
|
423
|
+
"or ensure that the name is correct."
|
424
|
+
end
|
425
|
+
|
407
426
|
# `output_mode` can be :all, :errors_only or :none.
|
408
427
|
# If not provided, it will be determined based on the `HIDE_COMMAND_OUTPUT` env var
|
409
428
|
# or the return value of `Shell.should_hide_output?`.
|
data/lib/cpl/version.rb
CHANGED
data/lib/cpl.rb
CHANGED
@@ -146,9 +146,22 @@ module Cpl
|
|
146
146
|
::Command::Base.all_commands.merge(deprecated_commands)
|
147
147
|
end
|
148
148
|
|
149
|
+
def self.process_option_params(params)
|
150
|
+
# Ensures that if no value is provided for a non-boolean option (e.g., `cpl command --option`),
|
151
|
+
# it defaults to an empty string instead of the option name (which is the default Thor behavior)
|
152
|
+
params[:lazy_default] ||= "" if params[:type] != :boolean
|
153
|
+
|
154
|
+
params
|
155
|
+
end
|
156
|
+
|
149
157
|
@commands_with_required_options = []
|
150
158
|
@commands_with_extra_options = []
|
151
159
|
|
160
|
+
::Command::Base.common_options.each do |option|
|
161
|
+
params = process_option_params(option[:params])
|
162
|
+
class_option(option[:name], **params)
|
163
|
+
end
|
164
|
+
|
152
165
|
all_base_commands.each do |command_key, command_class| # rubocop:disable Metrics/BlockLength
|
153
166
|
deprecated = deprecated_commands[command_key]
|
154
167
|
|
@@ -157,7 +170,7 @@ module Cpl
|
|
157
170
|
usage = command_class::USAGE.empty? ? name : command_class::USAGE
|
158
171
|
requires_args = command_class::REQUIRES_ARGS
|
159
172
|
default_args = command_class::DEFAULT_ARGS
|
160
|
-
command_options = command_class::OPTIONS
|
173
|
+
command_options = command_class::OPTIONS
|
161
174
|
accepts_extra_options = command_class::ACCEPTS_EXTRA_OPTIONS
|
162
175
|
description = command_class::DESCRIPTION
|
163
176
|
long_description = command_class::LONG_DESCRIPTION
|
@@ -175,12 +188,7 @@ module Cpl
|
|
175
188
|
long_desc(long_description)
|
176
189
|
|
177
190
|
command_options.each do |option|
|
178
|
-
params = option[:params]
|
179
|
-
|
180
|
-
# Ensures that if no value is provided for a non-boolean option (e.g., `cpl command --option`),
|
181
|
-
# it defaults to an empty string instead of the option name (which is the default Thor behavior)
|
182
|
-
params[:lazy_default] ||= "" if params[:type] != :boolean
|
183
|
-
|
191
|
+
params = process_option_params(option[:params])
|
184
192
|
method_option(option[:name], **params)
|
185
193
|
end
|
186
194
|
|
@@ -208,7 +216,7 @@ module Cpl
|
|
208
216
|
end
|
209
217
|
|
210
218
|
begin
|
211
|
-
Cpl::Cli.validate_options!(options
|
219
|
+
Cpl::Cli.validate_options!(options)
|
212
220
|
|
213
221
|
config = Config.new(args, options, required_options)
|
214
222
|
|
@@ -227,11 +235,11 @@ module Cpl
|
|
227
235
|
check_unknown_options!(except: @commands_with_extra_options)
|
228
236
|
stop_on_unknown_option!
|
229
237
|
|
230
|
-
def self.validate_options!(options
|
238
|
+
def self.validate_options!(options)
|
231
239
|
options.each do |name, value|
|
232
240
|
raise "No value provided for option '#{name}'." if value.to_s.strip.empty?
|
233
241
|
|
234
|
-
params =
|
242
|
+
params = ::Command::Base.all_options.find { |option| option[:name].to_s == name }[:params]
|
235
243
|
next unless params[:valid_regex]
|
236
244
|
|
237
245
|
raise "Invalid value provided for option '#{name}'." unless value.match?(params[:valid_regex])
|
data/templates/memcached.yml
CHANGED
@@ -4,8 +4,8 @@ spec:
|
|
4
4
|
type: standard
|
5
5
|
containers:
|
6
6
|
- name: memcached
|
7
|
-
cpu:
|
8
|
-
memory:
|
7
|
+
cpu: 25m
|
8
|
+
memory: 32Mi
|
9
9
|
args:
|
10
10
|
- "-l"
|
11
11
|
- 0.0.0.0
|
@@ -15,7 +15,7 @@ spec:
|
|
15
15
|
protocol: tcp
|
16
16
|
defaultOptions:
|
17
17
|
autoscaling:
|
18
|
-
metric:
|
18
|
+
metric: disabled
|
19
19
|
minScale: 1
|
20
20
|
maxScale: 1
|
21
21
|
capacityAI: false
|
data/templates/postgres.yml
CHANGED
data/templates/redis.yml
CHANGED
@@ -4,15 +4,15 @@ spec:
|
|
4
4
|
type: standard
|
5
5
|
containers:
|
6
6
|
- name: redis
|
7
|
-
cpu:
|
8
|
-
memory:
|
7
|
+
cpu: 25m
|
8
|
+
memory: 32Mi
|
9
9
|
image: "redis:latest"
|
10
10
|
ports:
|
11
11
|
- number: 6379
|
12
12
|
protocol: tcp
|
13
13
|
defaultOptions:
|
14
14
|
autoscaling:
|
15
|
-
metric:
|
15
|
+
metric: disabled
|
16
16
|
minScale: 1
|
17
17
|
maxScale: 1
|
18
18
|
capacityAI: false
|
@@ -0,0 +1,37 @@
|
|
1
|
+
kind: volumeset
|
2
|
+
name: redis-data
|
3
|
+
spec:
|
4
|
+
fileSystemType: ext4
|
5
|
+
initialCapacity: 10
|
6
|
+
performanceClass: general-purpose-ssd
|
7
|
+
---
|
8
|
+
kind: workload
|
9
|
+
name: redis2
|
10
|
+
spec:
|
11
|
+
type: stateful
|
12
|
+
containers:
|
13
|
+
- name: redis
|
14
|
+
args:
|
15
|
+
- '--appendonly'
|
16
|
+
- 'yes'
|
17
|
+
- '--maxmemory'
|
18
|
+
- 25mb
|
19
|
+
cpu: 25m
|
20
|
+
memory: 32Mi
|
21
|
+
image: "redis:latest"
|
22
|
+
ports:
|
23
|
+
- number: 6379
|
24
|
+
protocol: tcp
|
25
|
+
volumes:
|
26
|
+
- path: /data
|
27
|
+
recoveryPolicy: retain
|
28
|
+
uri: cpln://volumeset/redis-data
|
29
|
+
defaultOptions:
|
30
|
+
autoscaling:
|
31
|
+
metric: disabled
|
32
|
+
minScale: 1
|
33
|
+
maxScale: 1
|
34
|
+
capacityAI: false
|
35
|
+
firewallConfig:
|
36
|
+
internal:
|
37
|
+
inboundAllowType: same-gvc
|
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: 2.0.
|
4
|
+
version: 2.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: 2024-05-
|
12
|
+
date: 2024-05-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: debug
|
@@ -310,6 +310,7 @@ files:
|
|
310
310
|
- templates/postgres.yml
|
311
311
|
- templates/rails.yml
|
312
312
|
- templates/redis.yml
|
313
|
+
- templates/redis2.yml
|
313
314
|
- templates/secrets.yml
|
314
315
|
- templates/sidekiq.yml
|
315
316
|
homepage: https://github.com/shakacode/heroku-to-control-plane
|
@@ -328,9 +329,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
328
329
|
version: 2.7.0
|
329
330
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
330
331
|
requirements:
|
331
|
-
- - "
|
332
|
+
- - ">="
|
332
333
|
- !ruby/object:Gem::Version
|
333
|
-
version:
|
334
|
+
version: '0'
|
334
335
|
requirements: []
|
335
336
|
rubygems_version: 3.4.21
|
336
337
|
signing_key:
|