Skip to content

Commit

Permalink
Refactor UI related codebase (#630)
Browse files Browse the repository at this point in the history
  • Loading branch information
james03160927 authored Dec 20, 2023
1 parent cf3cdee commit 876c0ad
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 77 deletions.
33 changes: 23 additions & 10 deletions aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (

"github.com/gruntwork-io/cloud-nuke/config"
"github.com/gruntwork-io/cloud-nuke/logging"
"github.com/gruntwork-io/cloud-nuke/progressbar"
"github.com/gruntwork-io/cloud-nuke/report"
"github.com/gruntwork-io/cloud-nuke/telemetry"
"github.com/gruntwork-io/go-commons/collections"
Expand Down Expand Up @@ -75,7 +74,8 @@ func GetAllResources(c context.Context, query *Query, configObj config.Config) (
}
}

pterm.Info.Println("Done searching for resources")
logging.Info("Done searching for resources")
logging.Infof("Found total of %d resources", account.TotalResourceCount())
err := spinner.Stop()
if err != nil {
return nil, err
Expand Down Expand Up @@ -110,19 +110,21 @@ func IsNukeable(resourceType string, resourceTypes []string) bool {
return false
}

func nukeAllResourcesInRegion(account *AwsAccountResources, region string) {
func nukeAllResourcesInRegion(account *AwsAccountResources, region string, bar *pterm.ProgressbarPrinter) {
resourcesInRegion := account.Resources[region]

for _, resources := range resourcesInRegion.Resources {
length := len((*resources).ResourceIdentifiers())
for _, awsResource := range resourcesInRegion.Resources {
length := len((*awsResource).ResourceIdentifiers())

// Split api calls into batches
logging.Debugf("Terminating %d resources in batches", length)
batches := util.Split((*resources).ResourceIdentifiers(), (*resources).MaxBatchSize())
logging.Debugf("Terminating %d awsResource in batches", length)
batches := util.Split((*awsResource).ResourceIdentifiers(), (*awsResource).MaxBatchSize())

for i := 0; i < len(batches); i++ {
batch := batches[i]
if err := (*resources).Nuke(batch); err != nil {
bar.UpdateTitle(fmt.Sprintf("Nuking batch of %d %s resource(s) in %s",
len(batch), (*awsResource).ResourceName(), region))
if err := (*awsResource).Nuke(batch); err != nil {
// TODO: Figure out actual error type
if strings.Contains(err.Error(), "RequestLimitExceeded") {
logging.Debug(
Expand All @@ -142,6 +144,9 @@ func nukeAllResourcesInRegion(account *AwsAccountResources, region string) {
logging.Debug("Sleeping for 10 seconds before processing next batch...")
time.Sleep(10 * time.Second)
}

// Update the spinner to show the current resource type being nuked
bar.Add(len(batch))
}
}
}
Expand All @@ -150,7 +155,10 @@ func nukeAllResourcesInRegion(account *AwsAccountResources, region string) {
func NukeAllResources(account *AwsAccountResources, regions []string) error {
// Set the progressbar width to the total number of nukeable resources found
// across all regions
progressbar.StartProgressBarWithLength(account.TotalResourceCount())
progressBar, err := pterm.DefaultProgressbar.WithTotal(account.TotalResourceCount()).Start()
if err != nil {
return err
}

telemetry.TrackEvent(commonTelemetry.EventContext{
EventName: "Begin nuking resources",
Expand All @@ -166,7 +174,7 @@ func NukeAllResources(account *AwsAccountResources, regions []string) error {
// We intentionally do not handle an error returned from this method, because we collect individual errors
// on per-resource basis via the report package's Record method. In the run report displayed at the end of
// a cloud-nuke run, we show exactly which resources deleted cleanly and which encountered errors
nukeAllResourcesInRegion(account, region)
nukeAllResourcesInRegion(account, region, progressBar)
telemetry.TrackEvent(commonTelemetry.EventContext{
EventName: "Done Nuking Region",
}, map[string]interface{}{
Expand All @@ -175,5 +183,10 @@ func NukeAllResources(account *AwsAccountResources, regions []string) error {
})
}

_, err = progressBar.Stop()
if err != nil {
return err
}

return nil
}
14 changes: 11 additions & 3 deletions commands/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"github.com/gruntwork-io/cloud-nuke/aws"
"github.com/gruntwork-io/cloud-nuke/aws/resources"
"github.com/gruntwork-io/cloud-nuke/progressbar"
"os"
"time"

Expand Down Expand Up @@ -411,11 +410,20 @@ func nukeDefaultVpcs(c *cli.Context, regions []string) error {

if proceed || c.Bool("force") {
// Start nuke progress bar with correct number of items
progressbar.StartProgressBarWithLength(len(targetedRegionList))
err := resources.NukeVpcs(vpcPerRegion)
progressBar, err := pterm.DefaultProgressbar.WithTotal(len(targetedRegionList)).Start()
if err != nil {
return errors.WithStackTrace(err)
}

err = resources.NukeVpcs(vpcPerRegion)
if err != nil {
logging.Errorf("[Failed] %s", err)
}

_, err = progressBar.Stop()
if err != nil {
return errors.WithStackTrace(err)
}
}
return nil
}
Expand Down
35 changes: 0 additions & 35 deletions progressbar/progressbar.go

This file was deleted.

16 changes: 8 additions & 8 deletions report/record.go → report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package report

import (
"sync"

"github.com/gruntwork-io/cloud-nuke/progressbar"
)

var m = &sync.Mutex{}
/**
Using a global variables to keep track of reports & errors.
var generalErrors = make(map[string]GeneralError)
Generally, it is a bad idea to use global variables. However, in this case, it is the easiest way to keep track of
data that are running in parallel. We can explore passing reports/errors from individual resources in the future.
*/

// Global variables to keep track of errors/progress when nuking resources.
var m = &sync.Mutex{}
var generalErrors = make(map[string]GeneralError)
var records = make(map[string]Entry)

func GetRecords() map[string]Entry {
Expand All @@ -32,9 +36,6 @@ func Record(e Entry) {
defer m.Unlock()
m.Lock()
records[e.Identifier] = e
// Increment the progressbar so the user feels measurable progress on long-running nuke jobs
p := progressbar.GetProgressbar()
p.Increment()
}

// RecordBatch accepts a BatchEntry that contains a slice of identifiers, loops through them and converts each identifier to
Expand All @@ -56,7 +57,6 @@ func RecordError(e GeneralError) {
generalErrors[e.Description] = e
}

// Custom types
type Entry struct {
Identifier string
ResourceType string
Expand Down
28 changes: 7 additions & 21 deletions ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package ui
import (
"fmt"
"github.com/gruntwork-io/cloud-nuke/aws"
"github.com/gruntwork-io/cloud-nuke/util"
"github.com/gruntwork-io/go-commons/errors"
"io"
"os"
"strings"

"github.com/gruntwork-io/cloud-nuke/logging"
"github.com/gruntwork-io/cloud-nuke/progressbar"
"github.com/gruntwork-io/cloud-nuke/report"
"github.com/pterm/pterm"
)
Expand All @@ -20,12 +20,12 @@ import (
// which prints its own findings out directly to os.Stdout
func RenderRunReport() {
// Remove the progressbar, now that we're ready to display the table report
p := progressbar.GetProgressbar()
//p := GetProgressbar()
// This next entry is necessary to workaround an issue where the spinner is not reliably cleaned up before the
// final run report table is printed
fmt.Print("\r")
p.Stop()
pterm.Println()
//fmt.Print("\r")
//p.Stop()
//pterm.Println()

// Conditionally print the general error report, if in fact there were errors
PrintGeneralErrorReport(os.Stdout)
Expand Down Expand Up @@ -95,7 +95,8 @@ func PrintRunReport(w io.Writer) {
// responsive within a terminal, and this truncation allows rows to situate nicely within the table
//
// If we upgrade to a library that can render flexbox tables in the terminal we should revisit this
errSymbol = fmt.Sprintf("%s %s", FailureEmoji, truncate(removeNewlines(entry.Error.Error()), 40))
errSymbol = fmt.Sprintf("%s %s", FailureEmoji, util.Truncate(
util.RemoveNewlines(entry.Error.Error()), 40))
} else {
errSymbol = SuccessEmoji
}
Expand Down Expand Up @@ -129,21 +130,6 @@ func renderTableWithHeader(headers []string, data [][]string, w io.Writer) {
}
}

// truncate accepts a string and a max length. If the max length is less than the string's current length,
// then only the first maxLen characters of the string are returned
func truncate(s string, maxLen int) string {
if len(s) > maxLen {
return s[:maxLen]
}
return s
}

// removeNewlines will delete all the newlines in a given string, which is useful for making error messages
// "sit" more nicely within their specified table cells in the terminal
func removeNewlines(s string) string {
return strings.ReplaceAll(s, "\n", "")
}

func RenderResourcesAsTable(account *aws.AwsAccountResources) error {
var tableData [][]string
tableData = append(tableData, []string{"Resource Type", "Region", "Identifier"})
Expand Down
17 changes: 17 additions & 0 deletions util/string_utils.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package util

import "strings"

func Split(identifiers []string, limit int) [][]string {
if limit < 0 {
limit = -1 * limit
Expand Down Expand Up @@ -36,3 +38,18 @@ func Difference(a, b []*string) []*string {

return diff
}

// Truncate accepts a string and a max length. If the max length is less than the string's current length,
// then only the first maxLen characters of the string are returned
func Truncate(s string, maxLen int) string {
if len(s) > maxLen {
return s[:maxLen]
}
return s
}

// RemoveNewlines will delete all the newlines in a given string, which is useful for making error messages
// "sit" more nicely within their specified table cells in the terminal
func RemoveNewlines(s string) string {
return strings.ReplaceAll(s, "\n", "")
}

0 comments on commit 876c0ad

Please sign in to comment.