diff --git a/README.md b/README.md index 32efb6ee..f8a3da71 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This repo contains a CLI tool to delete all resources in an AWS account. cloud-nuke was created for situations when you might have an account you use for testing and need to clean up leftover resources so you're not charged for them. Also great for cleaning out accounts with redundant resources. Also great for removing unnecessary defaults like default VPCs and permissive ingress/egress rules in default security groups. In addition, cloud-nuke offers non-destructive inspecting functionality that can either be called via the command-line interface, or consumed as library methods, for scripting purposes. - + The currently supported functionality includes: ## AWS @@ -44,6 +44,7 @@ The currently supported functionality includes: - Inspecting and deleting all CloudWatch Log Groups in an AWS Account - Inspecting and deleting all GuardDuty Detectors in an AWS Account - Inspecting and deleting all Macie member accounts in an AWS account - as long as those accounts were created by Invitation - and not via AWS Organizations +- Inspecting and deleting all SageMaker Notebook Instances in an AWS account ### BEWARE! @@ -82,13 +83,13 @@ When using `cloud-nuke aws`, or `cloud-nuke inspect-aws`, you can use the `--reg cloud-nuke aws --region ap-south-1 --region ap-south-2 ``` -Similarly, the following command will inspect resources only in `us-east-1` +Similarly, the following command will inspect resources only in `us-east-1` ```shell cloud-nuke inspect-aws --region us-east-1 ``` -Including regions is available within: -- `cloud-nuke aws` +Including regions is available within: +- `cloud-nuke aws` - `cloud-nuke defaults-aws` - `cloud-nuke inspect-aws` @@ -108,8 +109,8 @@ cloud-nuke inspect-aws --exclude-region us-west-1 `--region` and `--exclude-region` flags cannot be specified together i.e. they are mutually exclusive. -Excluding regions is available within: -- `cloud-nuke aws` +Excluding regions is available within: +- `cloud-nuke aws` - `cloud-nuke defaults-aws` - `cloud-nuke inspect-aws` @@ -121,8 +122,8 @@ You can use the `--older-than` flag to only nuke resources that were created bef cloud-nuke aws --older-than 24h ``` -Excluding resources by age is available within: -- `cloud-nuke aws` +Excluding resources by age is available within: +- `cloud-nuke aws` - `cloud-nuke inspect-aws` @@ -134,8 +135,8 @@ You can use the `--list-resource-types` flag to list resource types whose termin cloud-nuke aws --list-resource-types ``` -Listing supported resource types is available within: -- `cloud-nuke aws` +Listing supported resource types is available within: +- `cloud-nuke aws` - `cloud-nuke inspect-aws` @@ -152,14 +153,14 @@ will search and target only `ec2` and `ami` resources. The specified resource ty i.e. it should be present in the `--list-resource-types` output. Using `--resource-type` also speeds up search because we are searching only for specific resource types. -Similarly, the following command will inspect only ec2 instances: +Similarly, the following command will inspect only ec2 instances: ```shell cloud-nuke inspect-aws --resource-type ec2 ``` -Specifying target resource types is available within: -- `cloud-nuke aws` +Specifying target resource types is available within: +- `cloud-nuke aws` - `cloud-nuke inspect-aws` ### Exclude terminating specific resource types @@ -175,8 +176,8 @@ This will terminate all resource types other than S3 and EC2. `--resource-type` and `--exclude-resource-type` flags cannot be specified together i.e. they are mutually exclusive. -Specifying resource types to exclude is available within: -- `cloud-nuke aws` +Specifying resource types to exclude is available within: +- `cloud-nuke aws` - `cloud-nuke inspect-aws` ### Dry run mode @@ -188,14 +189,14 @@ If you want to check what resources are going to be targeted without actually te cloud-nuke aws --resource-type ec2 --dry-run ``` -Dry run mode is only available within: +Dry run mode is only available within: - `cloud-nuke aws` ### Using cloud-nuke as a library -You can import cloud-nuke into other projects and use it as a library for programmatically inspecting and counting resources. +You can import cloud-nuke into other projects and use it as a library for programmatically inspecting and counting resources. -```golang +```golang package main @@ -333,6 +334,7 @@ The following resources support the Config file: - Config key: `CloudWatchLogGroup` - KMS customer keys - Resource type: `kmscustomerkeys` +<<<<<<< HEAD - Config key: `KMSCustomerKeys` - Auto Scaling Groups - Resource type: `asg` @@ -349,6 +351,13 @@ The following resources support the Config file: - EKS Clusters - Resource type: `ekscluster` - Config key: `EKSCluster` +- SageMaker Notebook Instances + - Resource type: `sagemaker-notebook-instances` + - Config key: `SageMakerNotebook` + +Notes: + * no configuration options for KMS customer keys, since keys are created with auto-generated identifier + #### Example @@ -459,11 +468,10 @@ To find out what we options are supported in the config file today, consult this | eks | none | ✅ | none | none | | acmpca | none | none | none | none | | iam role | none | none | none | none | +| sagemaker-notebook-instances| none| ✅ | none | none | | ... (more to come) | none | none | none | none | - - ### Log level You can set the log level by specifying the `--log-level` flag as per [logrus](https://github.com/sirupsen/logrus) log levels: diff --git a/aws/aws.go b/aws/aws.go index f1bab4cd..6ef7593c 100644 --- a/aws/aws.go +++ b/aws/aws.go @@ -220,7 +220,6 @@ func GetAllResources(targetRegions []string, excludeAfter time.Time, resourceTyp logging.Logger.Infof("Checking region [%d/%d]: %s", count, totalRegions, region) cloudNukeSession := newSession(region) - resourcesInRegion := AwsRegionResource{} // The order in which resources are nuked is important @@ -717,6 +716,7 @@ func GetAllResources(targetRegions []string, excludeAfter time.Time, resourceTyp } // End GuardDuty detectors + // Macie member accounts macieAccounts := MacieMember{} if IsNukeable(macieAccounts.ResourceName(), resourceTypes) { @@ -733,6 +733,20 @@ func GetAllResources(targetRegions []string, excludeAfter time.Time, resourceTyp } // End Macie member accounts + // Start SageMaker Notebook Instances + notebookInstances := SageMakerNotebookInstances{} + if IsNukeable(notebookInstances.ResourceName(), resourceTypes) { + instances, err := getAllNotebookInstances(cloudNukeSession, excludeAfter, configObj) + if err != nil { + return nil, errors.WithStackTrace(err) + } + if len(instances) > 0 { + notebookInstances.InstanceNames = awsgo.StringValueSlice(instances) + resourcesInRegion.Resources = append(resourcesInRegion.Resources, notebookInstances) + } + } + // End SageMaker Notebook Instances + if len(resourcesInRegion.Resources) > 0 { account.Resources[region] = resourcesInRegion } @@ -846,6 +860,7 @@ func ListResourceTypes() []string { CloudWatchLogGroups{}.ResourceName(), GuardDuty{}.ResourceName(), MacieMember{}.ResourceName(), + SageMakerNotebookInstances{}.ResourceName(), } sort.Strings(resourceTypes) return resourceTypes diff --git a/aws/sagemaker_notebook_instance.go b/aws/sagemaker_notebook_instance.go new file mode 100644 index 00000000..9b85e986 --- /dev/null +++ b/aws/sagemaker_notebook_instance.go @@ -0,0 +1,99 @@ +package aws + +import ( + "time" + + awsgo "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/sagemaker" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/logging" + "github.com/gruntwork-io/go-commons/errors" +) + +func getAllNotebookInstances(session *session.Session, excludeAfter time.Time, configObj config.Config) ([]*string, error) { + svc := sagemaker.New(session) + + result, err := svc.ListNotebookInstances(&sagemaker.ListNotebookInstancesInput{}) + + if err != nil { + return nil, errors.WithStackTrace(err) + } + + var names []*string + + for _, notebook := range result.NotebookInstances { + if notebook.CreationTime == nil { + continue + } + if !excludeAfter.After(awsgo.TimeValue(notebook.CreationTime)) { + continue + } + if !config.ShouldInclude(awsgo.StringValue(notebook.NotebookInstanceName), configObj.S3.IncludeRule.NamesRegExp, configObj.S3.ExcludeRule.NamesRegExp){ + continue + } + names = append(names, notebook.NotebookInstanceName) + } + + + return names, nil +} + +func nukeAllNotebookInstances(session *session.Session, names []*string) error { + svc := sagemaker.New(session) + + if len(names) == 0 { + logging.Logger.Infof("No Sagemaker Notebook Instance to nuke in region %s", *session.Config.Region) + return nil + } + + logging.Logger.Infof("Deleting all Sagemaker Notebook Instances in region %s", *session.Config.Region) + deletedNames := []*string{} + + for _, name := range names { + params := &sagemaker.DeleteNotebookInstanceInput{ + NotebookInstanceName: name, + } + + _, err := svc.StopNotebookInstance(&sagemaker.StopNotebookInstanceInput{ + NotebookInstanceName: name, + }) + if err != nil { + logging.Logger.Errorf("[Failed] %s: %s", *name, err) + } + + err = svc.WaitUntilNotebookInstanceStopped(&sagemaker.DescribeNotebookInstanceInput{ + NotebookInstanceName: name, + }) + + if err != nil { + logging.Logger.Errorf("[Failed] %s", err) + } + + _, err = svc.DeleteNotebookInstance(params) + + if err != nil { + logging.Logger.Errorf("[Failed] %s: %s", *name, err) + } else { + deletedNames = append(deletedNames, name) + logging.Logger.Infof("Deleted Sagemaker Notebook Instance: %s", awsgo.StringValue(name)) + } + } + + if len(deletedNames) > 0 { + for _, name := range deletedNames { + + err := svc.WaitUntilNotebookInstanceDeleted(&sagemaker.DescribeNotebookInstanceInput{ + NotebookInstanceName: name, + }) + + if err != nil { + logging.Logger.Errorf("[Failed] %s", err) + return errors.WithStackTrace(err) + } + } + } + + logging.Logger.Infof("[OK] %d Sagemaker Notebook Instance(s) deleted in %s", len(deletedNames), *session.Config.Region) + return nil +} diff --git a/aws/sagemaker_notebook_instance_test.go b/aws/sagemaker_notebook_instance_test.go new file mode 100644 index 00000000..4a117acd --- /dev/null +++ b/aws/sagemaker_notebook_instance_test.go @@ -0,0 +1,102 @@ +package aws + +import ( + "strings" + "testing" + "time" + + awsgo "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/sagemaker" + "github.com/gruntwork-io/cloud-nuke/config" + "github.com/gruntwork-io/cloud-nuke/logging" + "github.com/gruntwork-io/cloud-nuke/util" + "github.com/gruntwork-io/go-commons/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// There's a built-in function WaitUntilDBInstanceAvailable but +// the times that it was tested, it wasn't returning anything so we'll leave with the +// custom one. + +func waitUntilNotebookInstanceCreated(svc *sagemaker.SageMaker, name *string) error { + input := &sagemaker.DescribeNotebookInstanceInput{ + NotebookInstanceName: name, + } + + for i := 0; i < 600; i++ { + instance, err := svc.DescribeNotebookInstance(input) + status := instance.NotebookInstanceStatus + + if awsgo.StringValue(status) != "Pending" { + return nil + } + + if err != nil { + return err + } + + time.Sleep(1 * time.Second) + logging.Logger.Debug("Waiting for SageMaker Notebook Instance to be created") + } + + return SageMakerNotebookInstanceDeleteError{name: *name} +} + +func createTestNotebookInstance(t *testing.T, session *session.Session, name string, roleArn string) { + svc := sagemaker.New(session) + + params := &sagemaker.CreateNotebookInstanceInput{ + InstanceType: awsgo.String("ml.t2.medium"), + NotebookInstanceName: awsgo.String(name), + RoleArn: awsgo.String(roleArn), + } + + _, err := svc.CreateNotebookInstance(params) + require.NoError(t, err) + + waitUntilNotebookInstanceCreated(svc, &name) +} + +func TestNukeNotebookInstance(t *testing.T) { + t.Parallel() + + region, err := getRandomRegion() + + require.NoError(t, errors.WithStackTrace(err)) + + session, err := session.NewSessionWithOptions( + session.Options{ + SharedConfigState: session.SharedConfigEnable, + Config: awsgo.Config{ + Region: awsgo.String(region), + }, + }, + ) + + notebookName := "cloud-nuke-test-" + util.UniqueID() + excludeAfter := time.Now().Add(1 * time.Hour) + + role := createNotebookRole(t, session, notebookName+"-role") + defer deleteNotebookRole(session, role) + + createTestNotebookInstance(t, session, notebookName, *role.Arn) + + defer func() { + nukeAllNotebookInstances(session, []*string{¬ebookName}) + + notebookNames, _ := getAllNotebookInstances(session, excludeAfter, config.Config{}) + + assert.NotContains(t, awsgo.StringValueSlice(notebookNames), strings.ToLower(notebookName)) + }() + + instances, err := getAllNotebookInstances(session, excludeAfter, config.Config{}) + + if err != nil { + assert.Failf(t, "Unable to fetch list of SageMaker Notebook Instances", errors.WithStackTrace(err).Error()) + } + + assert.Contains(t, awsgo.StringValueSlice(instances), notebookName) + +} diff --git a/aws/sagemaker_notebook_instance_types.go b/aws/sagemaker_notebook_instance_types.go new file mode 100644 index 00000000..f100d153 --- /dev/null +++ b/aws/sagemaker_notebook_instance_types.go @@ -0,0 +1,42 @@ +package aws + +import ( + awsgo "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/gruntwork-io/go-commons/errors" +) + +type SageMakerNotebookInstances struct { + InstanceNames []string +} + +func (instance SageMakerNotebookInstances) ResourceName() string { + return "sagemaker-notebook-instance" +} + +// ResourceIdentifiers - The instance names of the rds db instances +func (instance SageMakerNotebookInstances) ResourceIdentifiers() []string { + return instance.InstanceNames +} + +func (instance SageMakerNotebookInstances) MaxBatchSize() int { + // Tentative batch size to ensure AWS doesn't throttle + return 200 +} + +// Nuke - nuke 'em all!!! +func (instance SageMakerNotebookInstances) Nuke(session *session.Session, identifiers []string) error { + if err := nukeAllNotebookInstances(session, awsgo.StringSlice(identifiers)); err != nil { + return errors.WithStackTrace(err) + } + + return nil +} + +type SageMakerNotebookInstanceDeleteError struct { + name string +} + +func (e SageMakerNotebookInstanceDeleteError) Error() string { + return "SageMaker Notebook Instance:" + e.name + "was not deleted" +} diff --git a/aws/sagemaker_notebook_instance_utils_for_test.go b/aws/sagemaker_notebook_instance_utils_for_test.go new file mode 100644 index 00000000..add1ca8d --- /dev/null +++ b/aws/sagemaker_notebook_instance_utils_for_test.go @@ -0,0 +1,123 @@ +package aws + +import ( + "testing" + + awsgo "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/iam" + gruntworkerrors "github.com/gruntwork-io/go-commons/errors" + "github.com/stretchr/testify/assert" +) + +func createNotebookRole(t *testing.T, awsSession *session.Session, roleName string) iam.Role { + svc := iam.New(awsSession) + createRoleParams := &iam.CreateRoleInput{ + AssumeRolePolicyDocument: awsgo.String(SAGEMAKER_ASSUME_ROLE_POLICY), + RoleName: awsgo.String(roleName), + } + + result, err := svc.CreateRole(createRoleParams) + if err != nil { + assert.Fail(t, gruntworkerrors.WithStackTrace(err).Error()) + } + putRolePolicyParams := &iam.PutRolePolicyInput{ + RoleName: awsgo.String(roleName), + PolicyDocument: awsgo.String(SAGEMAKER_ROLE_POLICY), + PolicyName: awsgo.String(roleName + "Policy"), + } + _, err = svc.PutRolePolicy(putRolePolicyParams) + if err != nil { + assert.Fail(t, gruntworkerrors.WithStackTrace(err).Error()) + } + return *result.Role +} + +func deleteNotebookRole(awsSession *session.Session, role iam.Role) error { + svc := iam.New(awsSession) + listRolePoliciesParams := &iam.ListRolePoliciesInput{ + RoleName: role.RoleName, + } + result, err := svc.ListRolePolicies(listRolePoliciesParams) + if err != nil { + return gruntworkerrors.WithStackTrace(err) + } + for _, policyName := range result.PolicyNames { + deleteRolePolicyParams := &iam.DeleteRolePolicyInput{ + RoleName: role.RoleName, + PolicyName: policyName, + } + _, err := svc.DeleteRolePolicy(deleteRolePolicyParams) + if err != nil { + return gruntworkerrors.WithStackTrace(err) + } + } + deleteRoleParams := &iam.DeleteRoleInput{ + RoleName: role.RoleName, + } + _, err = svc.DeleteRole(deleteRoleParams) + if err != nil { + return gruntworkerrors.WithStackTrace(err) + } + return nil +} + +const SAGEMAKER_ASSUME_ROLE_POLICY = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "sagemaker.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] + }` + +const SAGEMAKER_ROLE_POLICY = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "ec2:CreateTags", + "Resource": [ + "arn:aws:ec2:*:*:network-interface/*", + "arn:aws:ec2:*:*:security-group/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:CreateNetworkInterface", + "ec2:CreateSecurityGroup", + "ec2:DeleteNetworkInterface", + "ec2:DescribeDhcpOptions", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeSecurityGroups", + "ec2:DescribeSubnets", + "ec2:DescribeVpcs", + "ec2:ModifyNetworkInterfaceAttribute" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupEgress", + "ec2:AuthorizeSecurityGroupIngress", + "ec2:CreateNetworkInterfacePermission", + "ec2:DeleteNetworkInterfacePermission", + "ec2:DeleteSecurityGroup", + "ec2:RevokeSecurityGroupEgress", + "ec2:RevokeSecurityGroupIngress" + ], + "Resource": "*", + "Condition": { + "StringLike": { + "ec2:ResourceTag/ManagedByAmazonSageMakerResource": "*" + } + } + } + ] +}` diff --git a/config/config.go b/config/config.go index df11939b..d16c42a1 100644 --- a/config/config.go +++ b/config/config.go @@ -34,6 +34,7 @@ type Config struct { CloudWatchLogGroup ResourceType `yaml:"CloudWatchLogGroup"` KMSCustomerKeys ResourceType `yaml:"KMSCustomerKeys"` EKSCluster ResourceType `yaml:"EKSCluster"` + SageMakerNotebook ResourceType `yaml:"SageMakerNotebook"` } type ResourceType struct { diff --git a/config/config_test.go b/config/config_test.go index 321f92a1..af0dbcaf 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -35,6 +35,7 @@ func emptyConfig() *Config { ResourceType{FilterRule{}, FilterRule{}}, ResourceType{FilterRule{}, FilterRule{}}, ResourceType{FilterRule{}, FilterRule{}}, + ResourceType{FilterRule{}, FilterRule{}}, } } @@ -538,6 +539,99 @@ func TestConfigELBv2_FilterNames(t *testing.T) { return } +// SageMakerNotebookTests + +func TestConfigSageMakerNotebook_Empty(t *testing.T) { + configFilePath := "./mocks/sagemakernotebook_empty.yaml" + configObj, err := GetConfig(configFilePath) + + require.NoError(t, err) + + if !reflect.DeepEqual(configObj, emptyConfig()) { + assert.Fail(t, "Config should be empty, %+v\n", configObj.SageMakerNotebook) + } + + return +} + +func TestConfigSageMakerNotebook_EmptyFilters(t *testing.T) { + configFilePath := "./mocks/sagemakernotebook_empty_filters.yaml" + configObj, err := GetConfig(configFilePath) + + require.NoError(t, err) + + if !reflect.DeepEqual(configObj, emptyConfig()) { + assert.Fail(t, "Config should be empty, %+v\n", configObj) + } + + return +} + +func TestConfigSageMakerNotebook_EmptyRules(t *testing.T) { + configFilePath := "./mocks/sagemakernotebook_empty_rules.yaml" + configObj, err := GetConfig(configFilePath) + + require.NoError(t, err) + + if !reflect.DeepEqual(configObj, emptyConfig()) { + assert.Fail(t, "Config should be empty, %+v\n", configObj) + } + + return +} + +func TestConfigSageMakerNotebook_IncludeNames(t *testing.T) { + configFilePath := "./mocks/sagemakernotebook_include_names.yaml" + configObj, err := GetConfig(configFilePath) + + require.NoError(t, err) + + if reflect.DeepEqual(configObj, emptyConfig()) { + assert.Fail(t, "Config should not be empty, %+v\n", configObj) + } + + if len(configObj.SageMakerNotebook.IncludeRule.NamesRegExp) == 0 { + assert.Fail(t, "ConfigObj should contain SageMakerNotebook regexes, %+v\n", configObj) + } + + return +} + +func TestConfigSageMakerNotebook_ExcludeNames(t *testing.T) { + configFilePath := "./mocks/sagemakernotebook_exclude_names.yaml" + configObj, err := GetConfig(configFilePath) + + require.NoError(t, err) + + if reflect.DeepEqual(configObj, emptyConfig()) { + assert.Fail(t, "Config should not be empty, %+v\n", configObj) + } + + if len(configObj.SageMakerNotebook.ExcludeRule.NamesRegExp) == 0 { + assert.Fail(t, "ConfigObj should contain SageMakerNotebook regexes, %+v\n", configObj) + } + + return +} + +func TestConfigSageMakerNotebook_FilterNames(t *testing.T) { + configFilePath := "./mocks/sagemakernotebook_filter_names.yaml" + configObj, err := GetConfig(configFilePath) + + require.NoError(t, err) + + if reflect.DeepEqual(configObj, emptyConfig()) { + assert.Fail(t, "Config should not be empty, %+v\n", configObj) + } + + if len(configObj.SageMakerNotebook.IncludeRule.NamesRegExp) == 0 || + len(configObj.SageMakerNotebook.ExcludeRule.NamesRegExp) == 0 { + assert.Fail(t, "ConfigObj should contain SageMakerNotebook regexes, %+v\n", configObj) + } + + return +} + func TestShouldInclude_AllowWhenEmpty(t *testing.T) { var includeREs []Expression var excludeREs []Expression diff --git a/config/mocks/sagemakernotebook_cleanup.yaml b/config/mocks/sagemakernotebook_cleanup.yaml new file mode 100644 index 00000000..46355882 --- /dev/null +++ b/config/mocks/sagemakernotebook_cleanup.yaml @@ -0,0 +1,5 @@ +SageMakerNotebook: + include: + names_regex: + - ^cloud-nuke-test- + - -cloud-nuke-test- \ No newline at end of file diff --git a/config/mocks/sagemakernotebook_empty.yaml b/config/mocks/sagemakernotebook_empty.yaml new file mode 100644 index 00000000..1b6a9f07 --- /dev/null +++ b/config/mocks/sagemakernotebook_empty.yaml @@ -0,0 +1 @@ +SageMakerNotebook: \ No newline at end of file diff --git a/config/mocks/sagemakernotebook_empty_filters.yaml b/config/mocks/sagemakernotebook_empty_filters.yaml new file mode 100644 index 00000000..4186e069 --- /dev/null +++ b/config/mocks/sagemakernotebook_empty_filters.yaml @@ -0,0 +1,5 @@ +SageMakerNotebook: + include: + names_regex: + exclude: + names_regex: \ No newline at end of file diff --git a/config/mocks/sagemakernotebook_empty_rules.yaml b/config/mocks/sagemakernotebook_empty_rules.yaml new file mode 100644 index 00000000..0bf17499 --- /dev/null +++ b/config/mocks/sagemakernotebook_empty_rules.yaml @@ -0,0 +1,3 @@ +SageMakerNotebook: + include: + exclude: \ No newline at end of file diff --git a/config/mocks/sagemakernotebook_exclude_names.yaml b/config/mocks/sagemakernotebook_exclude_names.yaml new file mode 100644 index 00000000..86b13e2a --- /dev/null +++ b/config/mocks/sagemakernotebook_exclude_names.yaml @@ -0,0 +1,5 @@ +SageMakerNotebook: + exclude: + names_regex: + - alice + - bob \ No newline at end of file diff --git a/config/mocks/sagemakernotebook_filter_names.yaml b/config/mocks/sagemakernotebook_filter_names.yaml new file mode 100644 index 00000000..b983edf1 --- /dev/null +++ b/config/mocks/sagemakernotebook_filter_names.yaml @@ -0,0 +1,9 @@ +SageMakerNotebook: + include: + names_regex: + - ^cloud-nuke-* + - test + exclude: + names_regex: + - alice + - bob \ No newline at end of file diff --git a/config/mocks/sagemakernotebook_include_names.yaml b/config/mocks/sagemakernotebook_include_names.yaml new file mode 100644 index 00000000..4213b309 --- /dev/null +++ b/config/mocks/sagemakernotebook_include_names.yaml @@ -0,0 +1,5 @@ +SageMakerNotebook: + include: + names_regex: + - ^cloud-nuke-* + - test \ No newline at end of file