Repository: gruntwork-io/cloud-nuke
Pull request #768 (2024-09-21 07:32:21)

add support for eventBridge schedule & schedule groups.
## Description

Added support for [Amazon EventBridge Scheduler](https://docs.aws.amazon.com/eventbridge/latest/userguide/using-eventbridge-scheduler.html) - Schedules & Schedule group(s).

## TODOs

Read the [Gruntwork contribution guidelines](https://gruntwork.notion.site/Gruntwork-Coding-Methodology-02fdcd6e4b004e818553684760bf691e).

- [x] Update the docs.
- [x] Run the relevant tests successfully, including pre-commit checks.
- [x] Ensure any 3rd party code adheres with our [license policy](https://www.notion.so/gruntwork/Gruntwork-licenses-and-open-source-usage-policy-f7dece1f780341c7b69c1763f22b1378) or delete this line if its not applicable.
- [x] Include release notes. If this PR is backward incompatible, include a migration guide.
- [ ] Attention Grunts - if this PR adds support for a new resource, ensure the `nuke_sandbox` and `nuke_phxdevops` jobs in `.circleci/config.yml` have been updated with appropriate exclusions (either directly in the job or via the `.circleci/nuke_config.yml` file) to prevent nuking IAM roles, groups, resources, etc that are important for the test accounts.


## Release Notes (draft)

<!-- One-line description of the PR that can be included in the final release notes. -->
Added support for [Amazon EventBridge Scheduler](https://docs.aws.amazon.com/eventbridge/latest/userguide/using-eventbridge-scheduler.html) - Schedules & Schedule group(s).

### Migration Guide
n/a



Patch:
diff --git a/README.md b/README.md
index f20c10f..d2aa4a1 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,8 @@ Cloud-nuke suppports 🔎 inspecting and 🔥💀 deleting the following AWS res
 | Event Bridge            | Event buses                                              |
 | Event Bridge            | Archive                                                  |
 | Event Bridge            | Rule                                                     |
+| Event Bridge            | Schedule                                                 |
+| Event Bridge            | Schedule Group                                           |
 | Certificate Manager     | ACM Private CA                                           |
 | Direct Connect          | Transit Gateways                                         |
 | Elasticache             | Clusters                                                 |
@@ -599,6 +601,8 @@ of the file that are supported are listed here.
 | event-bridge                     | EventBridge                   | ✅ (Bus  Name)                         | ✅ (Creation Time)                   | ❌    | ✅       |
 | event-bridge-archive             | EventBridgeArchive            | ✅ (Archive Name)                      | ✅ (Creation Time)                   | ❌    | ✅       |
 | event-bridge-rule                | EventBridgeRule               | ✅ (Bus Rule Name)                     | ❌                                   | ❌    | ✅       |
+| event-bridge-schedule            | EventBridgeSchedule           | ✅ (Schedule Name)                     | ✅ (Creation Time)                   | ❌    | ✅       |
+| event-bridge-schedule-group      | EventBridgeScheduleGroup      | ✅ (Schedule Group Name)               | ✅ (Creation Time)                   | ❌    | ✅       |
 | guardduty                        | GuardDuty                     | ❌                                     | ✅ (Created Time)                    | ❌    | ✅       |
 | iam-group                        | IAMGroups                     | ✅ (Group Name)                        | ✅ (Creation Time)                   | ❌    | ✅       |
 | iam-policy                       | IAMPolicies                   | ✅ (Policy Name)                       | ✅ (Creation Time)                   | ❌    | ✅       |
diff --git a/aws/resource_registry.go b/aws/resource_registry.go
index 1699a86..625ba64 100644
--- a/aws/resource_registry.go
+++ b/aws/resource_registry.go
@@ -64,6 +64,8 @@ func getRegisteredRegionalResources() []AwsResource {
 		&resources.AppRunnerService{},
 		&resources.BackupVault{},
 		&resources.ManagedPrometheus{},
+		&resources.EventBridgeSchedule{},
+		&resources.EventBridgeScheduleGroup{},
 		&resources.EventBridgeArchive{},
 		&resources.EventBridgeRule{},
 		&resources.EventBridge{},
diff --git a/aws/resources/eventbridge_schedule.go b/aws/resources/eventbridge_schedule.go
new file mode 100644
index 0000000..bf20640
--- /dev/null
+++ b/aws/resources/eventbridge_schedule.go
@@ -0,0 +1,84 @@
+package resources
+
+import (
+	"context"
+	"fmt"
+	"strings"
+
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/gruntwork-io/cloud-nuke/logging"
+	"github.com/gruntwork-io/cloud-nuke/report"
+	"github.com/gruntwork-io/go-commons/errors"
+)
+
+func (sch *EventBridgeSchedule) nukeAll(identifiers []*string) error {
+	if len(identifiers) == 0 {
+		logging.Debugf("[Event Bridge Schedule] No Schedules found in region %s", sch.Region)
+		return nil
+	}
+
+	logging.Debugf("[Event Bridge Schedule] Deleting all Schedules in %s", sch.Region)
+
+	var deleted []*string
+	for _, identifier := range identifiers {
+		payload := strings.Split(*identifier, "|")
+		if len(payload) != 2 {
+			logging.Debugf("[Event Bridge Schedule] Invalid identifier %s", *identifier)
+			continue
+		}
+
+		_, err := sch.Client.DeleteSchedule(sch.Context, &scheduler.DeleteScheduleInput{
+			GroupName: aws.String(payload[0]),
+			Name:      aws.String(payload[1]),
+		})
+
+		if err != nil {
+			logging.Debugf(
+				"[Event Bridge Schedule] Error deleting Schedule %s in region %s, err %s",
+				*identifier,
+				sch.Region,
+				err,
+			)
+		} else {
+			deleted = append(deleted, identifier)
+			logging.Debugf("[Event Bridge Schedule] Deleted Schedule %s in region %s", *identifier, sch.Region)
+		}
+
+		e := report.Entry{
+			Identifier:   aws.ToString(identifier),
+			ResourceType: sch.ResourceName(),
+			Error:        err,
+		}
+		report.Record(e)
+	}
+
+	logging.Debugf("[OK] %d Event Bridges Schedul(es) deleted in %s", len(deleted), sch.Region)
+	return nil
+}
+
+func (sch *EventBridgeSchedule) getAll(ctx context.Context, cnfObj config.Config) ([]*string, error) {
+	var identifiers []*string
+
+	paginator := scheduler.NewListSchedulesPaginator(sch.Client, &scheduler.ListSchedulesInput{})
+	for paginator.HasMorePages() {
+		page, err := paginator.NextPage(ctx)
+		if err != nil {
+			logging.Debugf("[Event Bridge Schedule] Failed to list schedules: %s", err)
+			return nil, errors.WithStackTrace(err)
+		}
+
+		for _, schedule := range page.Schedules {
+			id := aws.String(fmt.Sprintf("%s|%s", *schedule.GroupName, *schedule.Name))
+			if cnfObj.EventBridgeSchedule.ShouldInclude(config.ResourceValue{
+				Name: id,
+				Time: schedule.CreationDate,
+			}) {
+				identifiers = append(identifiers, id)
+			}
+		}
+	}
+
+	return identifiers, nil
+}
diff --git a/aws/resources/eventbridge_schedule_group.go b/aws/resources/eventbridge_schedule_group.go
new file mode 100644
index 0000000..2e4f320
--- /dev/null
+++ b/aws/resources/eventbridge_schedule_group.go
@@ -0,0 +1,85 @@
+package resources
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler/types"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/gruntwork-io/cloud-nuke/logging"
+	"github.com/gruntwork-io/cloud-nuke/report"
+	"github.com/gruntwork-io/go-commons/errors"
+)
+
+func (sch *EventBridgeScheduleGroup) nukeAll(identifiers []*string) error {
+	if len(identifiers) == 0 {
+		logging.Debugf("[Event Bridge Schedule] No Groups found in region %s", sch.Region)
+		return nil
+	}
+
+	logging.Debugf("[Event Bridge Schedule] Deleting all Groups in %s", sch.Region)
+
+	var deleted []*string
+	for _, identifier := range identifiers {
+		_, err := sch.Client.DeleteScheduleGroup(sch.Context, &scheduler.DeleteScheduleGroupInput{
+			Name: identifier,
+		})
+
+		if err != nil {
+			logging.Debugf(
+				"[Event Bridge Schedule] Error deleting Group %s in region %s, err %s",
+				*identifier,
+				sch.Region,
+				err,
+			)
+		} else {
+			deleted = append(deleted, identifier)
+			logging.Debugf("[Event Bridge Schedule] Deleted Group %s in region %s", *identifier, sch.Region)
+		}
+
+		e := report.Entry{
+			Identifier:   aws.ToString(identifier),
+			ResourceType: sch.ResourceName(),
+			Error:        err,
+		}
+		report.Record(e)
+	}
+
+	logging.Debugf("[OK] %d Event Bridges Schedul Groups deleted in %s", len(deleted), sch.Region)
+	return nil
+}
+
+func (sch *EventBridgeScheduleGroup) getAll(ctx context.Context, cnfObj config.Config) ([]*string, error) {
+	var identifiers []*string
+	paginator := scheduler.NewListScheduleGroupsPaginator(sch.Client, &scheduler.ListScheduleGroupsInput{})
+
+	for paginator.HasMorePages() {
+		page, err := paginator.NextPage(ctx)
+		if err != nil {
+			logging.Debugf("[Event Bridge Schedule] Failed to list schedule groups: %s", err)
+			return nil, errors.WithStackTrace(err)
+		}
+
+		for _, group := range page.ScheduleGroups {
+			if cnfObj.EventBridgeScheduleGroup.ShouldInclude(config.ResourceValue{
+				Name: group.Name,
+				Time: group.CreationDate,
+			}) {
+				if *group.Name == "default" {
+					logging.Debug("[Event Bridge Schedule] skipping default group")
+					continue
+				}
+
+				if group.State != types.ScheduleGroupStateActive {
+					logging.Debugf("[Event Bridge Schedule] skipping group %s, wrong state %s", *group.Name, group.State)
+					continue
+				}
+
+				identifiers = append(identifiers, group.Name)
+			}
+		}
+	}
+
+	return identifiers, nil
+}
diff --git a/aws/resources/eventbridge_schedule_group_types.go b/aws/resources/eventbridge_schedule_group_types.go
new file mode 100644
index 0000000..337ec75
--- /dev/null
+++ b/aws/resources/eventbridge_schedule_group_types.go
@@ -0,0 +1,58 @@
+package resources
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/gruntwork-io/go-commons/errors"
+)
+
+type EventBridgeScheduleGroupAPI interface {
+	DeleteScheduleGroup(ctx context.Context, params *scheduler.DeleteScheduleGroupInput, optFns ...func(*scheduler.Options)) (*scheduler.DeleteScheduleGroupOutput, error)
+	ListScheduleGroups(ctx context.Context, params *scheduler.ListScheduleGroupsInput, optFns ...func(*scheduler.Options)) (*scheduler.ListScheduleGroupsOutput, error)
+}
+
+type EventBridgeScheduleGroup struct {
+	BaseAwsResource
+	Client EventBridgeScheduleGroupAPI
+	Region string
+	Groups []string
+}
+
+func (sch *EventBridgeScheduleGroup) GetAndSetResourceConfig(configObj config.Config) config.ResourceType {
+	return configObj.EventBridgeScheduleGroup
+}
+
+func (sch *EventBridgeScheduleGroup) InitV2(cfg aws.Config) {
+	sch.Client = scheduler.NewFromConfig(cfg)
+}
+
+func (sch *EventBridgeScheduleGroup) IsUsingV2() bool { return true }
+
+func (sch *EventBridgeScheduleGroup) ResourceName() string { return "event-bridge-schedule-group" }
+
+func (sch *EventBridgeScheduleGroup) ResourceIdentifiers() []string { return sch.Groups }
+
+func (sch *EventBridgeScheduleGroup) MaxBatchSize() int {
+	return 100
+}
+
+func (sch *EventBridgeScheduleGroup) Nuke(identifiers []string) error {
+	if err := sch.nukeAll(aws.StringSlice(identifiers)); err != nil {
+		return errors.WithStackTrace(err)
+	}
+
+	return nil
+}
+
+func (sch *EventBridgeScheduleGroup) GetAndSetIdentifiers(ctx context.Context, cnfObj config.Config) ([]string, error) {
+	identifiers, err := sch.getAll(ctx, cnfObj)
+	if err != nil {
+		return nil, err
+	}
+
+	sch.Groups = aws.ToStringSlice(identifiers)
+	return sch.Groups, nil
+}
diff --git a/aws/resources/eventbridge_schedule_types.go b/aws/resources/eventbridge_schedule_types.go
new file mode 100644
index 0000000..a1ef31f
--- /dev/null
+++ b/aws/resources/eventbridge_schedule_types.go
@@ -0,0 +1,58 @@
+package resources
+
+import (
+	"context"
+
+	"github.com/aws/aws-sdk-go-v2/aws"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/gruntwork-io/go-commons/errors"
+)
+
+type EventBridgeScheduleAPI interface {
+	DeleteSchedule(ctx context.Context, params *scheduler.DeleteScheduleInput, optFns ...func(*scheduler.Options)) (*scheduler.DeleteScheduleOutput, error)
+	ListSchedules(ctx context.Context, params *scheduler.ListSchedulesInput, optFns ...func(*scheduler.Options)) (*scheduler.ListSchedulesOutput, error)
+}
+
+type EventBridgeSchedule struct {
+	BaseAwsResource
+	Client EventBridgeScheduleAPI
+	Region    string
+	Schedules []string
+}
+
+func (sch *EventBridgeSchedule) GetAndSetResourceConfig(configObj config.Config) config.ResourceType {
+	return configObj.EventBridgeSchedule
+}
+
+func (sch *EventBridgeSchedule) InitV2(cfg aws.Config) {
+	sch.Client = scheduler.NewFromConfig(cfg)
+}
+
+func (sch *EventBridgeSchedule) IsUsingV2() bool { return true }
+
+func (sch *EventBridgeSchedule) ResourceName() string { return "event-bridge-schedule" }
+
+func (sch *EventBridgeSchedule) ResourceIdentifiers() []string { return sch.Schedules }
+
+func (sch *EventBridgeSchedule) MaxBatchSize() int {
+	return 100
+}
+
+func (sch *EventBridgeSchedule) Nuke(identifiers []string) error {
+	if err := sch.nukeAll(aws.StringSlice(identifiers)); err != nil {
+		return errors.WithStackTrace(err)
+	}
+
+	return nil
+}
+
+func (sch *EventBridgeSchedule) GetAndSetIdentifiers(ctx context.Context, cnfObj config.Config) ([]string, error) {
+	identifiers, err := sch.getAll(ctx, cnfObj)
+	if err != nil {
+		return nil, err
+	}
+
+	sch.Schedules = aws.ToStringSlice(identifiers)
+	return sch.Schedules, nil
+}
diff --git a/config/config.go b/config/config.go
index a34374c..a1aac29 100644
--- a/config/config.go
+++ b/config/config.go
@@ -74,6 +74,8 @@ type Config struct {
 	EventBridge                     ResourceType               `yaml:"EventBridge"`
 	EventBridgeArchive              ResourceType               `yaml:"EventBridgeArchive"`
 	EventBridgeRule                 ResourceType               `yaml:"EventBridgeRule"`
+	EventBridgeSchedule             ResourceType               `yaml:"EventBridgeSchedule"`
+	EventBridgeScheduleGroup        ResourceType               `yaml:"EventBridgeScheduleGroup"`
 	GuardDuty                       ResourceType               `yaml:"GuardDuty"`
 	IAMGroups                       ResourceType               `yaml:"IAMGroups"`
 	IAMPolicies                     ResourceType               `yaml:"IAMPolicies"`
diff --git a/go.mod b/go.mod
index 386eb5f..d1f83f8 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@ require (
 	github.com/aws/aws-sdk-go-v2/credentials v1.17.24
 	github.com/aws/aws-sdk-go-v2/service/amp v1.27.1
 	github.com/aws/aws-sdk-go-v2/service/eventbridge v1.33.7
+	github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7
 	github.com/charmbracelet/lipgloss v0.6.0
 	github.com/go-errors/errors v1.4.2
 	github.com/gruntwork-io/go-commons v0.17.0
diff --git a/go.sum b/go.sum
index 522d496..bf06a49 100644
--- a/go.sum
+++ b/go.sum
@@ -39,6 +39,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvG
 github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15 h1:I9zMeF107l0rJrpnHpjEiiTSCKYAIw8mALiXcPsGBiA=
 github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15/go.mod h1:9xWJ3Q/S6Ojusz1UIkfycgD1mGirJfLLKqq3LPT7WN8=
+github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7 h1:EcPyKUUo3neD2tDFKnq3TR3B9s2uZe9eWgxVQgixdzc=
+github.com/aws/aws-sdk-go-v2/service/scheduler v1.10.7/go.mod h1:MlNx35QVGG8TB2x1kOC0TKd9e93+RmFUE8HzYDLDLso=
 github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 h1:p1GahKIjyMDZtiKoIn0/jAj/TkMzfzndDv5+zi2Mhgc=
 github.com/aws/aws-sdk-go-v2/service/sso v1.22.1/go.mod h1:/vWdhoIoYA5hYoPZ6fm7Sv4d8701PiG5VKe8/pPJL60=
 github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 h1:ORnrOK0C4WmYV/uYt3koHEWBLYsRDwk2Np+eEoyV4Z0=


Test patch:
diff --git a/aws/resources/eventbridge_schedule_group_test.go b/aws/resources/eventbridge_schedule_group_test.go
new file mode 100644
index 0000000..9f0239d
--- /dev/null
+++ b/aws/resources/eventbridge_schedule_group_test.go
@@ -0,0 +1,104 @@
+package resources
+
+import (
+	"context"
+	"regexp"
+	"testing"
+	"time"
+
+	"github.com/aws/aws-sdk-go-v2/service/scheduler"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler/types"
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+type mockedEventBridgeScheduleGroupService struct {
+	EventBridgeScheduleGroupAPI
+	ListScheduleGroupsOutput  scheduler.ListScheduleGroupsOutput
+	DeleteScheduleGroupOutput scheduler.DeleteScheduleGroupOutput
+}
+
+func (m mockedEventBridgeScheduleGroupService) DeleteScheduleGroup(ctx context.Context, params *scheduler.DeleteScheduleGroupInput, optFns ...func(*scheduler.Options)) (*scheduler.DeleteScheduleGroupOutput, error) {
+	return &m.DeleteScheduleGroupOutput, nil
+}
+
+func (m mockedEventBridgeScheduleGroupService) ListScheduleGroups(ctx context.Context, params *scheduler.ListScheduleGroupsInput, optFns ...func(*scheduler.Options)) (*scheduler.ListScheduleGroupsOutput, error) {
+	return &m.ListScheduleGroupsOutput, nil
+}
+
+func Test_EventBridgeScheduleGroup_GetAll(t *testing.T) {
+	t.Parallel()
+
+	now := time.Now()
+
+	group1 := "test-group-1"
+	group2 := "test-group-2"
+
+	service := EventBridgeScheduleGroup{Client: mockedEventBridgeScheduleGroupService{
+		ListScheduleGroupsOutput: scheduler.ListScheduleGroupsOutput{
+			ScheduleGroups: []types.ScheduleGroupSummary{
+				{
+					Name:         aws.String(group1),
+					State:        types.ScheduleGroupStateActive,
+					CreationDate: &now,
+				},
+				{
+					Name:         aws.String(group2),
+					State:        types.ScheduleGroupStateActive,
+					CreationDate: aws.Time(now.Add(time.Hour)),
+				},
+			},
+		},
+	}}
+
+	tests := map[string]struct {
+		configObj config.ResourceType
+		expected  []string
+	}{
+		"emptyFilter": {
+			configObj: config.ResourceType{},
+			expected:  []string{group1, group2},
+		},
+		"nameExclusionFilter": {
+			configObj: config.ResourceType{
+				ExcludeRule: config.FilterRule{
+					NamesRegExp: []config.Expression{{
+						RE: *regexp.MustCompile(group1),
+					}},
+				}},
+			expected: []string{group2},
+		},
+		"timeAfterExclusionFilter": {
+			configObj: config.ResourceType{
+				ExcludeRule: config.FilterRule{
+					TimeAfter: aws.Time(now.Add(-1 * time.Hour)),
+				}},
+			expected: []string{},
+		},
+	}
+
+	for name, tc := range tests {
+		t.Run(name, func(t *testing.T) {
+			buses, err := service.getAll(
+				context.Background(),
+				config.Config{EventBridgeScheduleGroup: tc.configObj},
+			)
+			require.NoError(t, err)
+			require.Equal(t, tc.expected, aws.StringValueSlice(buses))
+		})
+	}
+}
+
+func Test_EventBridgeScheduleGroup_NukeAll(t *testing.T) {
+	t.Parallel()
+
+	groupName := "test-group"
+	service := EventBridgeScheduleGroup{Client: mockedEventBridgeScheduleGroupService{
+		DeleteScheduleGroupOutput: scheduler.DeleteScheduleGroupOutput{},
+	}}
+
+	err := service.nukeAll([]*string{&groupName})
+	assert.NoError(t, err)
+}
diff --git a/aws/resources/eventbridge_schedule_test.go b/aws/resources/eventbridge_schedule_test.go
new file mode 100644
index 0000000..0901a8b
--- /dev/null
+++ b/aws/resources/eventbridge_schedule_test.go
@@ -0,0 +1,110 @@
+package resources
+
+import (
+	"context"
+	"fmt"
+	"regexp"
+	"testing"
+	"time"
+
+	"github.com/aws/aws-sdk-go-v2/service/scheduler"
+	"github.com/aws/aws-sdk-go-v2/service/scheduler/types"
+	"github.com/aws/aws-sdk-go/aws"
+	"github.com/gruntwork-io/cloud-nuke/config"
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+)
+
+type mockedEventBridgeScheduleService struct {
+	EventBridgeScheduleAPI
+
+	ListSchedulesOutput  scheduler.ListSchedulesOutput
+	DeleteScheduleOutput scheduler.DeleteScheduleOutput
+}
+
+func (m mockedEventBridgeScheduleService) DeleteSchedule(ctx context.Context, params *scheduler.DeleteScheduleInput, optFns ...func(*scheduler.Options)) (*scheduler.DeleteScheduleOutput, error) {
+	return &m.DeleteScheduleOutput, nil
+}
+
+func (m mockedEventBridgeScheduleService) ListSchedules(ctx context.Context, params *scheduler.ListSchedulesInput, optFns ...func(*scheduler.Options)) (*scheduler.ListSchedulesOutput, error) {
+	return &m.ListSchedulesOutput, nil
+}
+
+func Test_EventBridgeSchedule_GetAll(t *testing.T) {
+	t.Parallel()
+
+	now := time.Now()
+
+	schedule1 := "test-group-1"
+	schedule2 := "test-group-2"
+
+	group := "test-default"
+	gSchedule1 := fmt.Sprintf("%s|%s", group, schedule1)
+	gSchedule2 := fmt.Sprintf("%s|%s", group, schedule2)
+
+	service := EventBridgeSchedule{
+		Client: mockedEventBridgeScheduleService{
+			ListSchedulesOutput: scheduler.ListSchedulesOutput{
+				Schedules: []types.ScheduleSummary{
+					{
+						GroupName:    aws.String(group),
+						Name:         aws.String(schedule1),
+						CreationDate: &now,
+					},
+					{
+						GroupName:    aws.String(group),
+						Name:         aws.String(schedule2),
+						CreationDate: aws.Time(now.Add(time.Hour)),
+					},
+				},
+			}}}
+
+	tests := map[string]struct {
+		configObj config.ResourceType
+		expected  []string
+	}{
+		"emptyFilter": {
+			configObj: config.ResourceType{},
+			expected:  []string{gSchedule1, gSchedule2},
+		},
+		"nameExclusionFilter": {
+			configObj: config.ResourceType{
+				ExcludeRule: config.FilterRule{
+					NamesRegExp: []config.Expression{{
+						RE: *regexp.MustCompile(schedule1),
+					}},
+				}},
+			expected: []string{gSchedule2},
+		},
+		"timeAfterExclusionFilter": {
+			configObj: config.ResourceType{
+				ExcludeRule: config.FilterRule{
+					TimeAfter: aws.Time(now.Add(-1 * time.Hour)),
+				}},
+			expected: []string{},
+		},
+	}
+
+	for name, tc := range tests {
+		t.Run(name, func(t *testing.T) {
+			buses, err := service.getAll(
+				context.Background(),
+				config.Config{EventBridgeSchedule: tc.configObj},
+			)
+			require.NoError(t, err)
+			require.Equal(t, tc.expected, aws.StringValueSlice(buses))
+		})
+	}
+}
+
+func Test_EventBridgeSchedule_NukeAll(t *testing.T) {
+	t.Parallel()
+
+	scheduleName := "test-schedule"
+	service := EventBridgeSchedule{Client: mockedEventBridgeScheduleService{
+		DeleteScheduleOutput: scheduler.DeleteScheduleOutput{},
+	}}
+
+	err := service.nukeAll([]*string{&scheduleName})
+	assert.NoError(t, err)
+}
diff --git a/config/config_test.go b/config/config_test.go
index 682c93c..4681f3c 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -66,6 +66,8 @@ func emptyConfig() *Config {
 		EventBridge:                     ResourceType{FilterRule{}, FilterRule{}, "", false},
 		EventBridgeArchive:              ResourceType{FilterRule{}, FilterRule{}, "", false},
 		EventBridgeRule:                 ResourceType{FilterRule{}, FilterRule{}, "", false},
+		EventBridgeSchedule:             ResourceType{FilterRule{}, FilterRule{}, "", false},
+		EventBridgeScheduleGroup:        ResourceType{FilterRule{}, FilterRule{}, "", false},
 		GuardDuty:                       ResourceType{FilterRule{}, FilterRule{}, "", false},
 		IAMGroups:                       ResourceType{FilterRule{}, FilterRule{}, "", false},
 		IAMPolicies:                     ResourceType{FilterRule{}, FilterRule{}, "", false},