Skip to content

Commit

Permalink
feat: initial implementing of passing context
Browse files Browse the repository at this point in the history
  • Loading branch information
ekristen committed Jan 14, 2024
1 parent faaafef commit 27bd4b8
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 42 deletions.
40 changes: 21 additions & 19 deletions pkg/nuke/nuke.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package nuke

import (
"context"
"fmt"
"io"
"slices"
Expand Down Expand Up @@ -161,7 +162,7 @@ func (n *Nuke) Prompt() error {

// Run is the main entry point for the library. It will run the validation handlers, prompt the user, scan for
// resources, filter them and then process them.
func (n *Nuke) Run() error {
func (n *Nuke) Run(ctx context.Context) error {
n.Version()

if err := n.Validate(); err != nil {
Expand All @@ -172,7 +173,7 @@ func (n *Nuke) Run() error {
return err
}

if err := n.Scan(); err != nil {
if err := n.Scan(ctx); err != nil {
return err
}

Expand All @@ -190,7 +191,7 @@ func (n *Nuke) Run() error {
return err
}

if err := n.run(); err != nil {
if err := n.run(ctx); err != nil {
return err
}

Expand All @@ -201,12 +202,12 @@ func (n *Nuke) Run() error {
}

// run handles the processing and loop of the queue of items
func (n *Nuke) run() error {
func (n *Nuke) run(ctx context.Context) error {
failCount := 0
waitingCount := 0

for {
n.HandleQueue()
n.HandleQueue(ctx)

if n.Queue.Count(
queue.ItemStatePending,
Expand Down Expand Up @@ -289,14 +290,14 @@ func (n *Nuke) Validate() error {
// Scan is used to scan for resources. It will run the scanners that were registered with the library by the invoking
// tool. It will also filter the resources based on the filters that were registered. It will also print the current
// status of the resources.
func (n *Nuke) Scan() error {
func (n *Nuke) Scan(ctx context.Context) error {
itemQueue := queue.Queue{
Items: make([]*queue.Item, 0),
}

for _, scanners := range n.Scanners {
for _, scanner := range scanners {
err := scanner.Run()
err := scanner.Run(ctx)
if err != nil {
return err
}
Expand Down Expand Up @@ -408,27 +409,27 @@ func (n *Nuke) Filter(item *queue.Item) error {

// HandleQueue is used to handle the queue of resources. It will iterate over the queue and trigger the appropriate
// handlers based on the state of the resource.
func (n *Nuke) HandleQueue() {
func (n *Nuke) HandleQueue(ctx context.Context) {
listCache := make(map[string]map[string][]resource.Resource)

for _, item := range n.Queue.GetItems() {
switch item.GetState() {
case queue.ItemStateNew:
n.HandleRemove(item)
n.HandleRemove(ctx, item)
item.Print()
case queue.ItemStateNewDependency, queue.ItemStatePendingDependency:
n.HandleWaitDependency(item)
n.HandleWaitDependency(ctx, item)
item.Print()
case queue.ItemStateFailed:
n.HandleRemove(item)
n.HandleWait(item, listCache)
n.HandleRemove(ctx, item)
n.HandleWait(ctx, item, listCache)
item.Print()
case queue.ItemStatePending:
n.HandleWait(item, listCache)
n.HandleWait(ctx, item, listCache)
item.State = queue.ItemStateWaiting
item.Print()
case queue.ItemStateWaiting:
n.HandleWait(item, listCache)
n.HandleWait(ctx, item, listCache)
item.Print()
}
}
Expand All @@ -450,7 +451,8 @@ func (n *Nuke) HandleQueue() {

// HandleRemove is used to handle the removal of a resource. It will remove the resource and set the state of the
// resource to pending if it was successful or failed if it was not.
func (n *Nuke) HandleRemove(item *queue.Item) {
func (n *Nuke) HandleRemove(_ context.Context, item *queue.Item) {
// TODO: pass context to remove for remove functions to use
err := item.Resource.Remove()
if err != nil {
item.State = queue.ItemStateFailed
Expand All @@ -464,7 +466,7 @@ func (n *Nuke) HandleRemove(item *queue.Item) {

// HandleWaitDependency is used to handle the waiting of a resource. It will check if the resource has any dependencies
// and if it does, it will check if the dependencies have been removed. If they have, it will trigger the remove handler.
func (n *Nuke) HandleWaitDependency(item *queue.Item) {
func (n *Nuke) HandleWaitDependency(ctx context.Context, item *queue.Item) {
reg := resource.GetRegistration(item.Type)
depCount := 0
for _, dep := range reg.DependsOn {
Expand All @@ -476,7 +478,7 @@ func (n *Nuke) HandleWaitDependency(item *queue.Item) {
}

if depCount == 0 {
n.HandleRemove(item)
n.HandleRemove(ctx, item)
return
}

Expand All @@ -486,7 +488,7 @@ func (n *Nuke) HandleWaitDependency(item *queue.Item) {

// HandleWait is used to handle the waiting of a resource. It will check if the resource has been removed. If it has,
// it will set the state of the resource to finished. If it has not, it will set the state of the resource to waiting.
func (n *Nuke) HandleWait(item *queue.Item, cache ListCache) {
func (n *Nuke) HandleWait(ctx context.Context, item *queue.Item, cache ListCache) {
var err error

ownerID := item.Owner
Expand All @@ -497,7 +499,7 @@ func (n *Nuke) HandleWait(item *queue.Item, cache ListCache) {

left, ok := cache[ownerID][item.Type]
if !ok {
left, err = item.List(item.Opts)
left, err = item.List(ctx, item.Opts)
if err != nil {
item.State = queue.ItemStateFailed
item.Reason = err.Error()
Expand Down
17 changes: 9 additions & 8 deletions pkg/nuke/nuke_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nuke

import (
"context"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -243,7 +244,7 @@ func Test_Nuke_Scan(t *testing.T) {
sErr := n.RegisterScanner(testScope, scanner)
assert.NoError(t, sErr)

err := n.Scan()
err := n.Scan(context.TODO())
assert.NoError(t, err)

assert.Equal(t, 2, n.Queue.Total())
Expand Down Expand Up @@ -280,7 +281,7 @@ func Test_Nuke_Filters_Match(t *testing.T) {
sErr := n.RegisterScanner(testScope, scanner)
assert.NoError(t, sErr)

err := n.Scan()
err := n.Scan(context.TODO())
assert.NoError(t, err)
assert.Equal(t, 1, n.Queue.Total())
assert.Equal(t, 1, n.Queue.Count(queue.ItemStateFiltered))
Expand Down Expand Up @@ -315,7 +316,7 @@ func Test_Nuke_Filters_NoMatch(t *testing.T) {
sErr := n.RegisterScanner(testScope, scanner)
assert.NoError(t, sErr)

err := n.Scan()
err := n.Scan(context.TODO())
assert.NoError(t, err)
assert.Equal(t, 1, n.Queue.Total())
assert.Equal(t, 0, n.Queue.Count(queue.ItemStateFiltered))
Expand Down Expand Up @@ -349,7 +350,7 @@ func Test_Nuke_Filters_ErrorCustomProps(t *testing.T) {
sErr := n.RegisterScanner(testScope, scanner)
assert.NoError(t, sErr)

err := n.Scan()
err := n.Scan(context.TODO())
assert.Error(t, err)
assert.Equal(t, "*nuke.TestResource does not support custom properties", err.Error())
}
Expand Down Expand Up @@ -423,7 +424,7 @@ func Test_Nuke_HandleRemove(t *testing.T) {
State: queue.ItemStateNew,
}

n.HandleRemove(i)
n.HandleRemove(context.TODO(), i)
assert.Equal(t, queue.ItemStatePending, i.State)
}

Expand All @@ -441,7 +442,7 @@ func Test_Nuke_HandleRemoveError(t *testing.T) {
State: queue.ItemStateNew,
}

n.HandleRemove(i)
n.HandleRemove(context.TODO(), i)
assert.Equal(t, queue.ItemStateFailed, i.State)
}

Expand Down Expand Up @@ -471,7 +472,7 @@ func Test_Nuke_Run(t *testing.T) {
sErr := n.RegisterScanner(testScope, scanner)
assert.NoError(t, sErr)

err := n.Run()
err := n.Run(context.TODO())
assert.NoError(t, err)
}

Expand Down Expand Up @@ -505,6 +506,6 @@ func Test_Nuke_Run_Error(t *testing.T) {
sErr := n.RegisterScanner(testScope, scanner)
assert.NoError(t, sErr)

err := n.Run()
err := n.Run(context.TODO())
assert.NoError(t, err)
}
14 changes: 8 additions & 6 deletions pkg/nuke/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ func (s *Scanner) RegisterMutateOptsFunc(morph MutateOptsFunc) {
}

// Run starts the scanner and runs the lister for each resource type.
func (s *Scanner) Run() error {
ctx := context.Background()

func (s *Scanner) Run(ctx context.Context) error {
for _, resourceType := range s.resourceTypes {
err := s.semaphore.Acquire(ctx, 1)
if err != nil {
Expand All @@ -75,7 +73,7 @@ func (s *Scanner) Run() error {
opts = s.mutateOptsFunc(opts, resourceType)
}

go s.list(s.owner, resourceType, opts)
go s.list(ctx, s.owner, resourceType, opts)
}

// Wait for all routines to finish.
Expand All @@ -89,20 +87,24 @@ func (s *Scanner) Run() error {
return nil
}

func (s *Scanner) list(owner, resourceType string, opts interface{}) {
func (s *Scanner) list(ctx context.Context, owner, resourceType string, opts interface{}) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()

defer func() {
if r := recover(); r != nil {
err := fmt.Errorf("%v\n\n%s", r.(error), string(debug.Stack()))
dump := utils.Indent(fmt.Sprintf("%v", err), " ")
logrus.Errorf("Listing %s failed:\n%s", resourceType, dump)
}
}()

defer s.semaphore.Release(1)

lister := resource.GetLister(resourceType)
var rs []resource.Resource

rs, err := lister.List(opts)
rs, err := lister.List(ctx, opts)
if err != nil {
var errSkipRequest sdkerrors.ErrSkipRequest
ok := errors.As(err, &errSkipRequest)
Expand Down
11 changes: 6 additions & 5 deletions pkg/nuke/scan_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nuke

import (
"context"
"flag"
"fmt"
"io"
Expand Down Expand Up @@ -102,7 +103,7 @@ type TestResourceLister struct {
RemoveError bool
}

func (l TestResourceLister) List(o interface{}) ([]resource.Resource, error) {
func (l TestResourceLister) List(_ context.Context, o interface{}) ([]resource.Resource, error) {
opts := o.(TestOpts)

if opts.ThrowError {
Expand Down Expand Up @@ -182,7 +183,7 @@ func Test_NewScannerWithMorphOpts(t *testing.T) {
scanner := NewScanner("owner", []string{testResourceType}, opts)
scanner.RegisterMutateOptsFunc(morphOpts)

err := scanner.Run()
err := scanner.Run(context.TODO())
assert.NoError(t, err)

assert.Len(t, scanner.Items, 1)
Expand Down Expand Up @@ -215,7 +216,7 @@ func Test_NewScannerWithResourceListerError(t *testing.T) {
}

scanner := NewScanner("owner", []string{testResourceType}, opts)
err := scanner.Run()
err := scanner.Run(context.TODO())
assert.NoError(t, err)

assert.Len(t, scanner.Items, 0)
Expand Down Expand Up @@ -248,7 +249,7 @@ func Test_NewScannerWithResourceListerErrorSkip(t *testing.T) {
}

scanner := NewScanner("owner", []string{testResourceType}, opts)
err := scanner.Run()
err := scanner.Run(context.TODO())
assert.NoError(t, err)

assert.Len(t, scanner.Items, 0)
Expand Down Expand Up @@ -281,7 +282,7 @@ func Test_NewScannerWithResourceListerErrorUnknownEndpoint(t *testing.T) {
}

scanner := NewScanner("owner", []string{testResourceType}, opts)
err := scanner.Run()
err := scanner.Run(context.TODO())
assert.NoError(t, err)

assert.Len(t, scanner.Items, 0)
Expand Down
5 changes: 3 additions & 2 deletions pkg/queue/item.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package queue

import (
"context"
"fmt"

"github.com/ekristen/libnuke/pkg/featureflag"
Expand Down Expand Up @@ -53,8 +54,8 @@ func (i *Item) GetReason() string {

// List calls the List method for the lister for the Type that belongs to the Item which returns
// a list of resources or an error. This primarily is used for the HandleWait function.
func (i *Item) List(opts interface{}) ([]resource.Resource, error) {
return resource.GetLister(i.Type).List(opts)
func (i *Item) List(ctx context.Context, opts interface{}) ([]resource.Resource, error) {
return resource.GetLister(i.Type).List(ctx, opts)
}

// GetProperty retrieves the string value of a property on the Item's Resource if it exists.
Expand Down
3 changes: 2 additions & 1 deletion pkg/resource/registry.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package resource

import (
"context"
"fmt"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -40,7 +41,7 @@ type Registration struct {

// Lister is an interface that represents a resource that can be listed
type Lister interface {
List(opts interface{}) ([]Resource, error)
List(ctx context.Context, opts interface{}) ([]Resource, error)
}

// RegisterOption is a function that can be used to manipulate the lister for a given resource type at
Expand Down
3 changes: 2 additions & 1 deletion pkg/resource/registry_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package resource

import (
"context"
"fmt"
"testing"

Expand All @@ -9,7 +10,7 @@ import (

type TestLister struct{}

func (l TestLister) List(o interface{}) ([]Resource, error) { return nil, nil }
func (l TestLister) List(_ context.Context, o interface{}) ([]Resource, error) { return nil, nil }

func Test_RegisterNoScope(t *testing.T) {
ClearRegistry()
Expand Down

0 comments on commit 27bd4b8

Please sign in to comment.