cpl 2.0.0.rc.1 → 2.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/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:
|