cpl 0.5.0 → 0.6.0
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/Gemfile.lock +3 -3
- data/docs/commands.md +39 -19
- data/lib/command/{setup.rb → apply_template.rb} +89 -15
- data/lib/command/base.rb +13 -2
- data/lib/command/deploy_image.rb +14 -4
- data/lib/command/run.rb +33 -12
- data/lib/command/run_detached.rb +17 -12
- data/lib/command/setup_app.rb +29 -0
- data/lib/core/controlplane.rb +6 -0
- data/lib/cpl/version.rb +1 -1
- data/lib/cpl.rb +6 -1
- data/lib/deprecated_commands.json +3 -2
- 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: cfd7383099c36f633d327424fcb36561e2b925120e63f1b814158a43bd55103f
|
4
|
+
data.tar.gz: eafdf0607fe28d3c24f8132e3a116085020c94639d5b05a5accec4d4de651ca5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b443d26a3fa91400dbb6d2e71b730a26bd1405df2f03e7f9446179323e2becb532ec69d81d93f22578fe8793dbabec9a2283efc16a107decdb5aaa9e4a615281
|
7
|
+
data.tar.gz: 34ab7670bc372af9b8991678de9d99a9c60429b3caebeeeb2775046a9be3d4a7fb7335d9cbeb3a6c2ba06bb29ef40ab7c2cffbcd20737cfb62eb4048b07a8926
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cpl (0.
|
4
|
+
cpl (0.6.0)
|
5
5
|
debug (~> 1.7.1)
|
6
6
|
dotenv (~> 2.8.1)
|
7
7
|
psych (~> 5.1.0)
|
@@ -20,7 +20,7 @@ GEM
|
|
20
20
|
dotenv (2.8.1)
|
21
21
|
iniparse (1.5.0)
|
22
22
|
io-console (0.6.0)
|
23
|
-
irb (1.6.
|
23
|
+
irb (1.6.4)
|
24
24
|
reline (>= 0.3.0)
|
25
25
|
json (2.6.3)
|
26
26
|
overcommit (0.60.0)
|
@@ -77,7 +77,7 @@ GEM
|
|
77
77
|
simplecov_json_formatter (~> 0.1)
|
78
78
|
simplecov-html (0.12.3)
|
79
79
|
simplecov_json_formatter (0.1.4)
|
80
|
-
stringio (3.0.
|
80
|
+
stringio (3.0.6)
|
81
81
|
thor (1.2.1)
|
82
82
|
unicode-display_width (2.4.2)
|
83
83
|
|
data/docs/commands.md
CHANGED
@@ -11,6 +11,30 @@ This `-a` option is used in most of the commands and will pick all other app con
|
|
11
11
|
|
12
12
|
### Commands
|
13
13
|
|
14
|
+
### `apply-template`
|
15
|
+
|
16
|
+
- Applies application-specific configs from templates (e.g., for every review-app)
|
17
|
+
- Publishes (creates or updates) those at Control Plane infrastructure
|
18
|
+
- Picks templates from the `.controlplane/templates` directory
|
19
|
+
- Templates are ordinary Control Plane templates but with variable preprocessing
|
20
|
+
|
21
|
+
**Preprocessed template variables:**
|
22
|
+
|
23
|
+
```
|
24
|
+
APP_GVC - basically GVC or app name
|
25
|
+
APP_LOCATION - default location
|
26
|
+
APP_ORG - organization
|
27
|
+
APP_IMAGE - will use latest app image
|
28
|
+
```
|
29
|
+
|
30
|
+
```sh
|
31
|
+
# Applies single template.
|
32
|
+
cpl apply-template redis -a $APP_NAME
|
33
|
+
|
34
|
+
# Applies several templates (practically creating full app).
|
35
|
+
cpl apply-template gvc postgres redis rails -a $APP_NAME
|
36
|
+
```
|
37
|
+
|
14
38
|
### `build-image`
|
15
39
|
|
16
40
|
- Builds and pushes the image to Control Plane
|
@@ -238,6 +262,13 @@ cpl run rails c -a $APP_NAME
|
|
238
262
|
# Uses a different image (which may not be promoted yet).
|
239
263
|
cpl run rails db:migrate -a $APP_NAME --image appimage:123 # Exact image name
|
240
264
|
cpl run rails db:migrate -a $APP_NAME --image latest # Latest sequential image
|
265
|
+
|
266
|
+
# Uses a different workload
|
267
|
+
cpl run bash -a $APP_NAME -w other-workload
|
268
|
+
|
269
|
+
# Overrides remote CPLN_TOKEN env variable with local token.
|
270
|
+
# Useful when need superuser rights in remote container
|
271
|
+
cpl run bash -a $APP_NAME --use-local-token
|
241
272
|
```
|
242
273
|
|
243
274
|
### `run:detached`
|
@@ -263,30 +294,19 @@ cpl run:detached rails db:migrate -a $APP_NAME --image latest
|
|
263
294
|
# Uses a different image (which may not be promoted yet).
|
264
295
|
cpl run:detached rails db:migrate -a $APP_NAME --image appimage:123 # Exact image name
|
265
296
|
cpl run:detached rails db:migrate -a $APP_NAME --image latest # Latest sequential image
|
266
|
-
```
|
267
|
-
|
268
|
-
### `setup`
|
269
297
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
- Templates are ordinary Control Plane templates but with variable preprocessing
|
298
|
+
# Uses a different workload
|
299
|
+
cpl run:detached rails db:migrate:status -a $APP_NAME -w other-workload
|
300
|
+
```
|
274
301
|
|
275
|
-
|
302
|
+
### `setup-app`
|
276
303
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
APP_ORG - organization
|
281
|
-
APP_IMAGE - will use latest app image
|
282
|
-
```
|
304
|
+
- Creates an app and all its workloads
|
305
|
+
- Specify the templates for the app and workloads through `setup` in the `.controlplane/controlplane.yml` file
|
306
|
+
- This should should only be used for temporary apps like review apps, never for persistent apps like production (to update workloads for those, use 'cpl apply-template' instead)
|
283
307
|
|
284
308
|
```sh
|
285
|
-
|
286
|
-
cpl setup redis -a $APP_NAME
|
287
|
-
|
288
|
-
# Applies several templates (practically creating full app).
|
289
|
-
cpl setup gvc postgres redis rails -a $APP_NAME
|
309
|
+
cpl setup-app -a $APP_NAME
|
290
310
|
```
|
291
311
|
|
292
312
|
### `version`
|
@@ -1,12 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Command
|
4
|
-
class
|
5
|
-
NAME = "
|
6
|
-
USAGE = "
|
4
|
+
class ApplyTemplate < Base # rubocop:disable Metrics/ClassLength
|
5
|
+
NAME = "apply-template"
|
6
|
+
USAGE = "apply-template TEMPLATE [TEMPLATE] ... [TEMPLATE]"
|
7
7
|
REQUIRES_ARGS = true
|
8
8
|
OPTIONS = [
|
9
|
-
app_option(required: true)
|
9
|
+
app_option(required: true),
|
10
|
+
skip_confirm_option
|
10
11
|
].freeze
|
11
12
|
DESCRIPTION = "Applies application-specific configs from templates"
|
12
13
|
LONG_DESCRIPTION = <<~DESC
|
@@ -27,28 +28,35 @@ module Command
|
|
27
28
|
EXAMPLES = <<~EX
|
28
29
|
```sh
|
29
30
|
# Applies single template.
|
30
|
-
cpl
|
31
|
+
cpl apply-template redis -a $APP_NAME
|
31
32
|
|
32
33
|
# Applies several templates (practically creating full app).
|
33
|
-
cpl
|
34
|
+
cpl apply-template gvc postgres redis rails -a $APP_NAME
|
34
35
|
```
|
35
36
|
EX
|
36
37
|
|
37
38
|
def call # rubocop:disable Metrics/MethodLength
|
39
|
+
ensure_templates!
|
40
|
+
|
38
41
|
@app_status = :existing
|
39
42
|
@created_workloads = []
|
40
43
|
@failed_workloads = []
|
44
|
+
@skipped_workloads = []
|
41
45
|
|
42
|
-
|
43
|
-
filename = "#{config.app_cpln_dir}/templates/#{template}.yml"
|
46
|
+
@asked_for_confirmation = false
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
pending_templates = templates.select do |template|
|
49
|
+
if template == "gvc"
|
50
|
+
confirm_app(template)
|
51
|
+
else
|
52
|
+
confirm_workload(template)
|
53
|
+
end
|
54
|
+
end
|
48
55
|
|
49
|
-
|
50
|
-
end
|
56
|
+
progress.puts if @asked_for_confirmation
|
51
57
|
|
58
|
+
pending_templates.each do |template, filename|
|
59
|
+
step("Applying template '#{template}'", abort_on_error: false) do
|
52
60
|
apply_template(filename)
|
53
61
|
if $CHILD_STATUS.success?
|
54
62
|
report_success(template)
|
@@ -63,10 +71,58 @@ module Command
|
|
63
71
|
print_app_status
|
64
72
|
print_created_workloads
|
65
73
|
print_failed_workloads
|
74
|
+
print_skipped_workloads
|
66
75
|
end
|
67
76
|
|
68
77
|
private
|
69
78
|
|
79
|
+
def templates
|
80
|
+
@templates ||= config.args.to_h do |template|
|
81
|
+
[template, "#{config.app_cpln_dir}/templates/#{template}.yml"]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def ensure_templates!
|
86
|
+
missing_templates = templates.filter { |_template, filename| !File.exist?(filename) }.to_h
|
87
|
+
return if missing_templates.empty?
|
88
|
+
|
89
|
+
missing_templates_str = missing_templates.map do |template, filename|
|
90
|
+
" - #{template} (#{filename})"
|
91
|
+
end.join("\n")
|
92
|
+
progress.puts("#{Shell.color('Missing templates:', :red)}\n#{missing_templates_str}\n\n")
|
93
|
+
|
94
|
+
raise "Can't find templates above, please create them."
|
95
|
+
end
|
96
|
+
|
97
|
+
def confirm_apply(message)
|
98
|
+
return true if config.options[:yes]
|
99
|
+
|
100
|
+
@asked_for_confirmation = true
|
101
|
+
Shell.confirm(message)
|
102
|
+
end
|
103
|
+
|
104
|
+
def confirm_app(template)
|
105
|
+
app = cp.fetch_gvc
|
106
|
+
return true unless app
|
107
|
+
|
108
|
+
confirmed = confirm_apply("App '#{config.app}' already exists, do you want to re-create it?")
|
109
|
+
return true if confirmed
|
110
|
+
|
111
|
+
report_skipped(template)
|
112
|
+
false
|
113
|
+
end
|
114
|
+
|
115
|
+
def confirm_workload(template)
|
116
|
+
workload = cp.fetch_workload(template)
|
117
|
+
return true unless workload
|
118
|
+
|
119
|
+
confirmed = confirm_apply("Workload '#{template}' already exists, do you want to re-create it?")
|
120
|
+
return true if confirmed
|
121
|
+
|
122
|
+
report_skipped(template)
|
123
|
+
false
|
124
|
+
end
|
125
|
+
|
70
126
|
def apply_template(filename)
|
71
127
|
data = File.read(filename)
|
72
128
|
.gsub("APP_GVC", config.app)
|
@@ -93,13 +149,24 @@ module Command
|
|
93
149
|
end
|
94
150
|
end
|
95
151
|
|
152
|
+
def report_skipped(template)
|
153
|
+
if template == "gvc"
|
154
|
+
@app_status = :skipped
|
155
|
+
else
|
156
|
+
@skipped_workloads.push(template)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
96
160
|
def print_app_status
|
97
161
|
return if @app_status == :existing
|
98
162
|
|
99
|
-
|
163
|
+
case @app_status
|
164
|
+
when :success
|
100
165
|
progress.puts("\n#{Shell.color("Created app '#{config.app}'.", :green)}")
|
101
|
-
|
166
|
+
when :failure
|
102
167
|
progress.puts("\n#{Shell.color("Failed to create app '#{config.app}'.", :red)}")
|
168
|
+
when :skipped
|
169
|
+
progress.puts("\n#{Shell.color("Skipped app '#{config.app}' (already exists).", :blue)}")
|
103
170
|
end
|
104
171
|
end
|
105
172
|
|
@@ -116,5 +183,12 @@ module Command
|
|
116
183
|
workloads = @failed_workloads.map { |template| " - #{template}" }.join("\n")
|
117
184
|
progress.puts("\n#{Shell.color('Failed to create workloads:', :red)}\n#{workloads}")
|
118
185
|
end
|
186
|
+
|
187
|
+
def print_skipped_workloads
|
188
|
+
return unless @skipped_workloads.any?
|
189
|
+
|
190
|
+
workloads = @skipped_workloads.map { |template| " - #{template}" }.join("\n")
|
191
|
+
progress.puts("\n#{Shell.color('Skipped workloads (already exist):', :blue)}\n#{workloads}")
|
192
|
+
end
|
119
193
|
end
|
120
194
|
end
|
data/lib/command/base.rb
CHANGED
@@ -142,13 +142,24 @@ module Command
|
|
142
142
|
}
|
143
143
|
end
|
144
144
|
|
145
|
+
def self.use_local_token_option(required: false)
|
146
|
+
{
|
147
|
+
name: :use_local_token,
|
148
|
+
params: {
|
149
|
+
desc: "Override remote CPLN_TOKEN with local token",
|
150
|
+
type: :boolean,
|
151
|
+
required: required
|
152
|
+
}
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
145
156
|
def self.all_options
|
146
157
|
methods.grep(/_option$/).map { |method| send(method.to_s) }
|
147
158
|
end
|
148
159
|
|
149
160
|
def self.all_options_by_key_name
|
150
161
|
all_options.each_with_object({}) do |option, result|
|
151
|
-
option[:params][:aliases]
|
162
|
+
option[:params][:aliases]&.each { |current_alias| result[current_alias.to_s] = option }
|
152
163
|
result["--#{option[:name]}"] = option
|
153
164
|
end
|
154
165
|
end
|
@@ -168,7 +179,7 @@ module Command
|
|
168
179
|
|
169
180
|
def wait_for_replica(workload, location)
|
170
181
|
wait_for("replica") do
|
171
|
-
cp.
|
182
|
+
cp.workload_get_replicas_safely(workload, location: location)&.dig("items", 0)
|
172
183
|
end
|
173
184
|
end
|
174
185
|
|
data/lib/command/deploy_image.rb
CHANGED
@@ -11,18 +11,28 @@ module Command
|
|
11
11
|
- Deploys the latest image to app workloads
|
12
12
|
DESC
|
13
13
|
|
14
|
-
def call
|
14
|
+
def call # rubocop:disable Metrics/MethodLength
|
15
|
+
deployed_endpoints = {}
|
16
|
+
|
15
17
|
image = latest_image
|
16
18
|
|
17
19
|
config[:app_workloads].each do |workload|
|
18
|
-
cp.fetch_workload!(workload)
|
20
|
+
workload_data = cp.fetch_workload!(workload)
|
21
|
+
workload_data.dig("spec", "containers").each do |container|
|
19
22
|
next unless container["image"].match?(%r{^/org/#{config.org}/image/#{config.app}:})
|
20
23
|
|
21
|
-
|
22
|
-
|
24
|
+
container_name = container["name"]
|
25
|
+
step("Deploying image '#{image}' for workload '#{container_name}'") do
|
26
|
+
cp.workload_set_image_ref(workload, container: container_name, image: image)
|
27
|
+
deployed_endpoints[container_name] = workload_data.dig("status", "endpoint")
|
23
28
|
end
|
24
29
|
end
|
25
30
|
end
|
31
|
+
|
32
|
+
progress.puts("\nDeployed endpoints:")
|
33
|
+
deployed_endpoints.each do |workload, endpoint|
|
34
|
+
progress.puts(" - #{workload}: #{endpoint}")
|
35
|
+
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
end
|
data/lib/command/run.rb
CHANGED
@@ -8,7 +8,9 @@ module Command
|
|
8
8
|
DEFAULT_ARGS = ["bash"].freeze
|
9
9
|
OPTIONS = [
|
10
10
|
app_option(required: true),
|
11
|
-
image_option
|
11
|
+
image_option,
|
12
|
+
workload_option,
|
13
|
+
use_local_token_option
|
12
14
|
].freeze
|
13
15
|
DESCRIPTION = "Runs one-off **_interactive_** replicas (analog of `heroku run`)"
|
14
16
|
LONG_DESCRIPTION = <<~DESC
|
@@ -34,19 +36,25 @@ module Command
|
|
34
36
|
# Uses a different image (which may not be promoted yet).
|
35
37
|
cpl run rails db:migrate -a $APP_NAME --image appimage:123 # Exact image name
|
36
38
|
cpl run rails db:migrate -a $APP_NAME --image latest # Latest sequential image
|
39
|
+
|
40
|
+
# Uses a different workload
|
41
|
+
cpl run bash -a $APP_NAME -w other-workload
|
42
|
+
|
43
|
+
# Overrides remote CPLN_TOKEN env variable with local token.
|
44
|
+
# Useful when need superuser rights in remote container
|
45
|
+
cpl run bash -a $APP_NAME --use-local-token
|
37
46
|
```
|
38
47
|
EX
|
39
48
|
|
40
|
-
attr_reader :location, :workload, :one_off
|
49
|
+
attr_reader :location, :workload, :one_off, :container
|
41
50
|
|
42
51
|
def call
|
43
52
|
@location = config[:default_location]
|
44
|
-
@workload = config[:one_off_workload]
|
53
|
+
@workload = config.options["workload"] || config[:one_off_workload]
|
45
54
|
@one_off = "#{workload}-run-#{rand(1000..9999)}"
|
46
55
|
|
47
56
|
clone_workload
|
48
57
|
wait_for_workload(one_off)
|
49
|
-
sleep 2 # sometimes replica query lags workload creation, despite ok by prev query
|
50
58
|
wait_for_replica(one_off, location)
|
51
59
|
run_in_replica
|
52
60
|
ensure
|
@@ -60,15 +68,16 @@ module Command
|
|
60
68
|
|
61
69
|
# Create a base copy of workload props
|
62
70
|
spec = cp.fetch_workload!(workload).fetch("spec")
|
63
|
-
|
71
|
+
container_spec = spec["containers"].detect { _1["name"] == workload } || spec["containers"].first
|
72
|
+
@container = container_spec["name"]
|
64
73
|
|
65
74
|
# remove other containers if any
|
66
|
-
spec["containers"] = [
|
75
|
+
spec["containers"] = [container_spec]
|
67
76
|
|
68
77
|
# Stub workload command with dummy server that just responds to port
|
69
78
|
# Needed to avoid execution of ENTRYPOINT and CMD of Dockerfile
|
70
|
-
|
71
|
-
|
79
|
+
container_spec["command"] = "ruby"
|
80
|
+
container_spec["args"] = ["-e", Scripts.http_dummy_server_ruby]
|
72
81
|
|
73
82
|
# Ensure one-off workload will be running
|
74
83
|
spec["defaultOptions"]["suspend"] = false
|
@@ -81,11 +90,15 @@ module Command
|
|
81
90
|
# Override image if specified
|
82
91
|
image = config.options[:image]
|
83
92
|
image = "/org/#{config.org}/image/#{latest_image}" if image == "latest"
|
84
|
-
|
93
|
+
container_spec["image"] = image if image
|
85
94
|
|
86
95
|
# Set runner
|
87
|
-
|
88
|
-
|
96
|
+
container_spec["env"] ||= []
|
97
|
+
container_spec["env"] << { "name" => "CONTROLPLANE_RUNNER", "value" => runner_script }
|
98
|
+
|
99
|
+
if config.options["use_local_token"]
|
100
|
+
container_spec["env"] << { "name" => "CONTROLPLANE_TOKEN", "value" => ControlplaneApiDirect.new.api_token }
|
101
|
+
end
|
89
102
|
|
90
103
|
# Create workload clone
|
91
104
|
cp.apply("kind" => "workload", "name" => one_off, "spec" => spec)
|
@@ -93,6 +106,14 @@ module Command
|
|
93
106
|
|
94
107
|
def runner_script
|
95
108
|
script = Scripts.helpers_cleanup
|
109
|
+
|
110
|
+
if config.options["use_local_token"]
|
111
|
+
script += <<~SHELL
|
112
|
+
CPLN_TOKEN=$CONTROLPLANE_TOKEN
|
113
|
+
unset CONTROLPLANE_TOKEN
|
114
|
+
SHELL
|
115
|
+
end
|
116
|
+
|
96
117
|
script += args_join(config.args)
|
97
118
|
script
|
98
119
|
end
|
@@ -100,7 +121,7 @@ module Command
|
|
100
121
|
def run_in_replica
|
101
122
|
progress.puts "- Connecting"
|
102
123
|
command = %(bash -c 'eval "$CONTROLPLANE_RUNNER"')
|
103
|
-
cp.workload_exec(one_off, location: location, container:
|
124
|
+
cp.workload_exec(one_off, location: location, container: container, command: command)
|
104
125
|
end
|
105
126
|
end
|
106
127
|
end
|
data/lib/command/run_detached.rb
CHANGED
@@ -7,7 +7,8 @@ module Command
|
|
7
7
|
REQUIRES_ARGS = true
|
8
8
|
OPTIONS = [
|
9
9
|
app_option(required: true),
|
10
|
-
image_option
|
10
|
+
image_option,
|
11
|
+
workload_option
|
11
12
|
].freeze
|
12
13
|
DESCRIPTION = "Runs one-off **_non-interactive_** replicas (close analog of `heroku run:detached`)"
|
13
14
|
LONG_DESCRIPTION = <<~DESC
|
@@ -33,16 +34,19 @@ module Command
|
|
33
34
|
# Uses a different image (which may not be promoted yet).
|
34
35
|
cpl run:detached rails db:migrate -a $APP_NAME --image appimage:123 # Exact image name
|
35
36
|
cpl run:detached rails db:migrate -a $APP_NAME --image latest # Latest sequential image
|
37
|
+
|
38
|
+
# Uses a different workload
|
39
|
+
cpl run:detached rails db:migrate:status -a $APP_NAME -w other-workload
|
36
40
|
```
|
37
41
|
EX
|
38
42
|
|
39
43
|
WORKLOAD_SLEEP_CHECK = 2
|
40
44
|
|
41
|
-
attr_reader :location, :workload, :one_off
|
45
|
+
attr_reader :location, :workload, :one_off, :container
|
42
46
|
|
43
47
|
def call
|
44
48
|
@location = config[:default_location]
|
45
|
-
@workload = config[:one_off_workload]
|
49
|
+
@workload = config.options["workload"] || config[:one_off_workload]
|
46
50
|
@one_off = "#{workload}-runner-#{rand(1000..9999)}"
|
47
51
|
|
48
52
|
clone_workload
|
@@ -60,14 +64,15 @@ module Command
|
|
60
64
|
|
61
65
|
# Get base specs of workload
|
62
66
|
spec = cp.fetch_workload!(workload).fetch("spec")
|
63
|
-
|
67
|
+
container_spec = spec["containers"].detect { _1["name"] == workload } || spec["containers"].first
|
68
|
+
@container = container_spec["name"]
|
64
69
|
|
65
70
|
# remove other containers if any
|
66
|
-
spec["containers"] = [
|
71
|
+
spec["containers"] = [container_spec]
|
67
72
|
|
68
73
|
# Set runner
|
69
|
-
|
70
|
-
|
74
|
+
container_spec["command"] = "bash"
|
75
|
+
container_spec["args"] = ["-c", 'eval "$CONTROLPLANE_RUNNER"']
|
71
76
|
|
72
77
|
# Ensure one-off workload will be running
|
73
78
|
spec["defaultOptions"]["suspend"] = false
|
@@ -80,17 +85,17 @@ module Command
|
|
80
85
|
# Override image if specified
|
81
86
|
image = config.options[:image]
|
82
87
|
image = "/org/#{config.org}/image/#{latest_image}" if image == "latest"
|
83
|
-
|
88
|
+
container_spec["image"] = image if image
|
84
89
|
|
85
90
|
# Set cron job props
|
86
91
|
spec["type"] = "cron"
|
87
92
|
spec["job"] = { "schedule" => "* * * * *", "restartPolicy" => "Never" }
|
88
93
|
spec["defaultOptions"]["autoscaling"] = {}
|
89
|
-
|
94
|
+
container_spec.delete("ports")
|
90
95
|
|
91
|
-
|
92
|
-
|
93
|
-
|
96
|
+
container_spec["env"] ||= []
|
97
|
+
container_spec["env"] << { "name" => "CONTROLPLANE_TOKEN", "value" => ControlplaneApiDirect.new.api_token }
|
98
|
+
container_spec["env"] << { "name" => "CONTROLPLANE_RUNNER", "value" => runner_script }
|
94
99
|
|
95
100
|
# Create workload clone
|
96
101
|
cp.apply("kind" => "workload", "name" => one_off, "spec" => spec)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Command
|
4
|
+
class SetupApp < Base
|
5
|
+
NAME = "setup-app"
|
6
|
+
OPTIONS = [
|
7
|
+
app_option(required: true)
|
8
|
+
].freeze
|
9
|
+
DESCRIPTION = "Creates an app and all its workloads"
|
10
|
+
LONG_DESCRIPTION = <<~DESC
|
11
|
+
- Creates an app and all its workloads
|
12
|
+
- Specify the templates for the app and workloads through `setup` in the `.controlplane/controlplane.yml` file
|
13
|
+
- This should should only be used for temporary apps like review apps, never for persistent apps like production (to update workloads for those, use 'cpl apply-template' instead)
|
14
|
+
DESC
|
15
|
+
|
16
|
+
def call
|
17
|
+
templates = config[:setup].join(" ")
|
18
|
+
|
19
|
+
app = cp.fetch_gvc
|
20
|
+
if app
|
21
|
+
raise "App '#{config.app}' already exists. If you want to update this app, " \
|
22
|
+
"either run 'cpl delete -a #{config.app}' and then re-run this command, " \
|
23
|
+
"or run 'cpl apply-template #{templates} -a #{config.app}'."
|
24
|
+
end
|
25
|
+
|
26
|
+
perform("cpl apply-template #{templates} -a #{config.app}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/core/controlplane.rb
CHANGED
@@ -130,6 +130,12 @@ class Controlplane # rubocop:disable Metrics/ClassLength
|
|
130
130
|
perform_yaml(cmd)
|
131
131
|
end
|
132
132
|
|
133
|
+
def workload_get_replicas_safely(workload, location:)
|
134
|
+
cmd = "cpln workload get-replicas #{workload} #{gvc_org} --location #{location} -o yaml 2> /dev/null"
|
135
|
+
result = `#{cmd}`
|
136
|
+
$CHILD_STATUS.success? ? YAML.safe_load(result) : nil
|
137
|
+
end
|
138
|
+
|
133
139
|
def workload_set_image_ref(workload, container:, image:)
|
134
140
|
cmd = "cpln workload update #{workload} #{gvc_org}"
|
135
141
|
cmd += " --set spec.containers.#{container}.image=/org/#{config.org}/image/#{image}"
|
data/lib/cpl/version.rb
CHANGED
data/lib/cpl.rb
CHANGED
@@ -9,7 +9,12 @@ require "tempfile"
|
|
9
9
|
require "thor"
|
10
10
|
require "yaml"
|
11
11
|
|
12
|
-
|
12
|
+
# We need to require base before all commands, since the commands inherit from it
|
13
|
+
require_relative "command/base"
|
14
|
+
|
15
|
+
modules = Dir["#{__dir__}/**/*.rb"].reject do |file|
|
16
|
+
file == __FILE__ || file.end_with?("main.rb") || file.end_with?("base.rb")
|
17
|
+
end
|
13
18
|
modules.sort.each { require(_1) }
|
14
19
|
|
15
20
|
# Fix for https://github.com/erikhuda/thor/issues/398
|
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: 0.
|
4
|
+
version: 0.6.0
|
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-04-
|
12
|
+
date: 2023-04-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: debug
|
@@ -183,6 +183,7 @@ files:
|
|
183
183
|
- examples/circleci.yml
|
184
184
|
- examples/controlplane.yml
|
185
185
|
- googlee2da545df05d92f9.html
|
186
|
+
- lib/command/apply_template.rb
|
186
187
|
- lib/command/base.rb
|
187
188
|
- lib/command/build_image.rb
|
188
189
|
- lib/command/cleanup_old_images.rb
|
@@ -205,7 +206,7 @@ files:
|
|
205
206
|
- lib/command/ps_stop.rb
|
206
207
|
- lib/command/run.rb
|
207
208
|
- lib/command/run_detached.rb
|
208
|
-
- lib/command/
|
209
|
+
- lib/command/setup_app.rb
|
209
210
|
- lib/command/test.rb
|
210
211
|
- lib/command/version.rb
|
211
212
|
- lib/core/config.rb
|
@@ -250,7 +251,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
250
251
|
- !ruby/object:Gem::Version
|
251
252
|
version: '0'
|
252
253
|
requirements: []
|
253
|
-
rubygems_version: 3.4.
|
254
|
+
rubygems_version: 3.4.12
|
254
255
|
signing_key:
|
255
256
|
specification_version: 4
|
256
257
|
summary: Heroku to Control Plane
|