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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0be2530a33ac1f8a6b71d6d90eca0026b1048faf76b3e2f88cf13572f7e50a92
4
- data.tar.gz: c15e191f5d8e984aece73bf5954ba977ee1c3013851447592ef4f2e96c1e2732
3
+ metadata.gz: cfd7383099c36f633d327424fcb36561e2b925120e63f1b814158a43bd55103f
4
+ data.tar.gz: eafdf0607fe28d3c24f8132e3a116085020c94639d5b05a5accec4d4de651ca5
5
5
  SHA512:
6
- metadata.gz: 9fe01da2ec88fdb25ba56b9ca78267f8cca42b73f219576decc4af5c0aa695168d08b32692bcdcabc7274ab1f5e9f587d3d7b09d18817c262f011fc328ee7409
7
- data.tar.gz: a88847f98eaa1426eeabe23919cd1dbbf31275491e61ba825eebb44ae991b8eba087ffa1c61986e9f576026dbac59f4f118f00abcbfdfb273997ba95c1b27cdc
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.5.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.3)
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.5)
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
- - Applies application-specific configs from templates (e.g., for every review-app)
271
- - Publishes (creates or updates) those at Control Plane infrastructure
272
- - Picks templates from the `.controlplane/templates` directory
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
- **Preprocessed template variables:**
302
+ ### `setup-app`
276
303
 
277
- ```
278
- APP_GVC - basically GVC or app name
279
- APP_LOCATION - default location
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
- # Applies single template.
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 Setup < Base
5
- NAME = "setup"
6
- USAGE = "setup TEMPLATE [TEMPLATE] ... [TEMPLATE]"
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 setup redis -a $APP_NAME
31
+ cpl apply-template redis -a $APP_NAME
31
32
 
32
33
  # Applies several templates (practically creating full app).
33
- cpl setup gvc postgres redis rails -a $APP_NAME
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
- config.args.each do |template|
43
- filename = "#{config.app_cpln_dir}/templates/#{template}.yml"
46
+ @asked_for_confirmation = false
44
47
 
45
- step("Applying template '#{template}'", abort_on_error: false) do
46
- unless File.exist?(filename)
47
- report_failure(template)
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
- raise "Can't find template '#{template}' at '#{filename}', please create it."
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
- if @app_status == :success
163
+ case @app_status
164
+ when :success
100
165
  progress.puts("\n#{Shell.color("Created app '#{config.app}'.", :green)}")
101
- else
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].each { |current_alias| result[current_alias.to_s] = option }
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.workload_get_replicas(workload, location: location)&.dig("items", 0)
182
+ cp.workload_get_replicas_safely(workload, location: location)&.dig("items", 0)
172
183
  end
173
184
  end
174
185
 
@@ -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).dig("spec", "containers").each do |container|
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
- step("Deploying image '#{image}' for workload '#{container['name']}'") do
22
- cp.workload_set_image_ref(workload, container: container["name"], image: image)
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
- container = spec["containers"].detect { _1["name"] == workload } || spec["containers"].first
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"] = [container]
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
- container["command"] = "ruby"
71
- container["args"] = ["-e", Scripts.http_dummy_server_ruby]
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
- container["image"] = image if image
93
+ container_spec["image"] = image if image
85
94
 
86
95
  # Set runner
87
- container["env"] ||= []
88
- container["env"] << { "name" => "CONTROLPLANE_RUNNER", "value" => runner_script }
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: workload, command: command)
124
+ cp.workload_exec(one_off, location: location, container: container, command: command)
104
125
  end
105
126
  end
106
127
  end
@@ -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
- container = spec["containers"].detect { _1["name"] == workload } || spec["containers"].first
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"] = [container]
71
+ spec["containers"] = [container_spec]
67
72
 
68
73
  # Set runner
69
- container["command"] = "bash"
70
- container["args"] = ["-c", 'eval "$CONTROLPLANE_RUNNER"']
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
- container["image"] = image if image
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
- container.delete("ports")
94
+ container_spec.delete("ports")
90
95
 
91
- container["env"] ||= []
92
- container["env"] << { "name" => "CONTROLPLANE_TOKEN", "value" => ControlplaneApiDirect.new.api_token }
93
- container["env"] << { "name" => "CONTROLPLANE_RUNNER", "value" => runner_script }
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cpl
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0"
5
5
  end
data/lib/cpl.rb CHANGED
@@ -9,7 +9,12 @@ require "tempfile"
9
9
  require "thor"
10
10
  require "yaml"
11
11
 
12
- modules = Dir["#{__dir__}/**/*.rb"].reject { |file| file == __FILE__ || file.end_with?("main.rb") }
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
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "build": "build-image",
3
3
  "promote": "deploy-image",
4
- "promote-image": "deploy-image",
5
- "runner": "run:detached"
4
+ "promote_image": "deploy-image",
5
+ "runner": "run:detached",
6
+ "setup": "apply-template"
6
7
  }
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.5.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-06 00:00:00.000000000 Z
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/setup.rb
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.6
254
+ rubygems_version: 3.4.12
254
255
  signing_key:
255
256
  specification_version: 4
256
257
  summary: Heroku to Control Plane