Skip to content

Commit

Permalink
Fix issue where delete command fails to delete apps with volumesets (#…
Browse files Browse the repository at this point in the history
…123)

* feat: add api methods for listing/deleting volumesets

* fix: delete command fails to delete apps with volumesets

* docs: update CHANGELOG
  • Loading branch information
rafaelgomesxyz authored Jan 4, 2024
1 parent ab53a31 commit b116126
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ _Please add entries here for your pull requests that are not yet released._

- Fixed issue where `info` command does not respect `CPLN_ORG` env var. [PR 88](https://github.com/shakacode/heroku-to-control-plane/pull/88) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
- Fixed issues with running `cpl --version` and `cpl --help` where no configuration file exists. [PR 100](https://github.com/shakacode/heroku-to-control-plane/pull/100) by [Mostafa Ahangarha](https://github.com/ahangarha).
- Fixed issue where `delete` command fails to delete apps with volumesets. [PR 123](https://github.com/shakacode/heroku-to-control-plane/pull/123) by [Rafael Gomes](https://github.com/rafaelgomesxyz).

### Added

Expand Down
2 changes: 1 addition & 1 deletion docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ cpl copy-image-from-upstream -a $APP_NAME --upstream-token $UPSTREAM_TOKEN --ima

### `delete`

- Deletes the whole app (GVC with all workloads and all images)
- Deletes the whole app (GVC with all workloads, all volumesets and all images)
- Will ask for explicit user confirmation

```sh
Expand Down
51 changes: 40 additions & 11 deletions lib/command/delete.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,45 @@ class Delete < Base
app_option(required: true),
skip_confirm_option
].freeze
DESCRIPTION = "Deletes the whole app (GVC with all workloads and all images)"
DESCRIPTION = "Deletes the whole app (GVC with all workloads, all volumesets and all images)"
LONG_DESCRIPTION = <<~DESC
- Deletes the whole app (GVC with all workloads and all images)
- Deletes the whole app (GVC with all workloads, all volumesets and all images)
- Will ask for explicit user confirmation
DESC

def call
return progress.puts("App '#{config.app}' does not exist.") if cp.fetch_gvc.nil?

check_volumesets
check_images
return unless confirm_delete

delete_volumesets
delete_gvc
delete_images
end

private

def check_volumesets
@volumesets = cp.fetch_volumesets["items"]
return progress.puts("No volumesets to delete.") unless @volumesets.any?

message = "The following volumesets will be deleted along with the app:"
volumesets_list = @volumesets.map { |volumeset| "- #{volumeset['name']}" }.join("\n")
progress.puts("#{Shell.color(message, :red)}\n#{volumesets_list}\n\n")
end

def check_images
@images = cp.query_images["items"]
.select { |image| image["name"].start_with?("#{config.app}:") }
return progress.puts("No images to delete.") unless @images.any?

message = "The following images will be deleted along with the app:"
images_list = @images.map { |image| "- #{image['name']}" }.join("\n")
progress.puts("#{Shell.color(message, :red)}\n#{images_list}\n\n")
end

def confirm_delete
return true if config.options[:yes]

Expand All @@ -33,22 +57,27 @@ def confirm_delete
end

def delete_gvc
return progress.puts("App '#{config.app}' does not exist.") if cp.fetch_gvc.nil?

step("Deleting app '#{config.app}'") do
cp.gvc_delete
end
end

def delete_images
images = cp.query_images["items"]
.filter_map { |item| item["name"] if item["name"].start_with?("#{config.app}:") }
def delete_volumesets
@volumesets.each do |volumeset|
step("Deleting volumeset '#{volumeset['name']}'") do
# If the volumeset is attached to a workload, we need to delete the workload first
workload = volumeset.dig("status", "usedByWorkload")&.split("/")&.last
cp.delete_workload(workload) if workload

return progress.puts("No images to delete.") unless images.any?
cp.delete_volumeset(volumeset["name"])
end
end
end

images.each do |image|
step("Deleting image '#{image}'") do
cp.image_delete(image)
def delete_images
@images.each do |image|
step("Deleting image '#{image['name']}'") do
cp.image_delete(image["name"])
end
end
end
Expand Down
10 changes: 10 additions & 0 deletions lib/core/controlplane.rb
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@ def workload_exec(workload, location:, container: nil, command: nil)
perform!(cmd)
end

# volumeset

def fetch_volumesets(a_gvc = gvc)
api.list_volumesets(org: org, gvc: a_gvc)
end

def delete_volumeset(volumeset, a_gvc = gvc)
api.delete_volumeset(org: org, gvc: a_gvc, volumeset: volumeset)
end

# domain

def find_domain_route(data)
Expand Down
10 changes: 9 additions & 1 deletion lib/core/controlplane_api.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

class ControlplaneApi
class ControlplaneApi # rubocop:disable Metrics/ClassLength
def gvc_list(org:)
api_json("/org/#{org}/gvc", method: :get)
end
Expand Down Expand Up @@ -86,6 +86,14 @@ def delete_workload(org:, gvc:, workload:)
api_json("/org/#{org}/gvc/#{gvc}/workload/#{workload}", method: :delete)
end

def list_volumesets(org:, gvc:)
api_json("/org/#{org}/gvc/#{gvc}/volumeset", method: :get)
end

def delete_volumeset(org:, gvc:, volumeset:)
api_json("/org/#{org}/gvc/#{gvc}/volumeset/#{volumeset}", method: :delete)
end

def list_domains(org:)
api_json("/org/#{org}/domain", method: :get)
end
Expand Down

0 comments on commit b116126

Please sign in to comment.