This document describes the test sweeper infrastructure for cleaning up leaked test resources.
Sweepers clean up resources that were created during acceptance tests but failed to be destroyed. This can happen when:
- Tests fail before cleanup
- API errors prevent deletion
- Developer interrupts tests
- Partial test runs leave resources behind
make sweepmake sweeperTF_ACC=1 go test ./internal/sweep -v -sweep=default -sweep-run=crowdstrike_host_groupSweepers use structured logging with configurable log levels. Set the SWEEP_LOG_LEVEL environment variable to control output verbosity:
# Show only warnings and errors (default: INFO)
SWEEP_LOG_LEVEL=WARN make sweep
# Show all logs including trace messages (useful for debugging)
SWEEP_LOG_LEVEL=TRACE make sweep
# Available levels: TRACE, DEBUG, INFO, WARN, ERRORLog levels:
- TRACE - Detailed debug information including all skipped resources
- DEBUG - Debug information
- INFO - General operational information (default)
- WARN - Warning messages for non-critical issues
- ERROR - Error messages
Example with trace logging:
SWEEP_LOG_LEVEL=TRACE make sweep
# Output includes: [TRACE] Skipping Prevention Policy production-policy (not a test resource)Sweepers require the same environment variables as acceptance tests:
FALCON_CLIENT_ID- CrowdStrike API client IDFALCON_CLIENT_SECRET- CrowdStrike API client secretFALCON_CLOUD- (optional) Cloud region
WARNING: Sweepers will delete infrastructure. Only run in development/test accounts.
All test resources MUST use the sweep.ResourcePrefix constant (defined as "tf-acc-test-" in internal/sweep/sweep.go) to be identified by sweepers.
Example:
name := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) // "tf-acc-test-abc123"The following sweepers are currently registered:
crowdstrike_host_group- Host groupscrowdstrike_prevention_policy- Prevention policies (Windows, Linux, Mac)crowdstrike_sensor_update_policy- Sensor update policiescrowdstrike_content_update_policy- Content update policies (RT Response)crowdstrike_cloud_aws_account- AWS cloud account registrationscrowdstrike_cloud_gcp_account- GCP cloud account registrationscrowdstrike_ioa_rule_group- Custom IOA rule groupscrowdstrike_firewall_rule_group- Firewall rule groupscrowdstrike_sensor_visibility_exclusion- Sensor visibility exclusionscrowdstrike_data_protection_content_pattern- Data protection content patternscrowdstrike_cloud_compliance_custom_framework- Cloud compliance custom frameworkscrowdstrike_cloud_group- Cloud groupscrowdstrike_cloud_security_custom_rule- Cloud security custom rulescrowdstrike_cloud_security_kac_policy- Cloud security KAC policiescrowdstrike_it_automation_task- IT automation taskscrowdstrike_it_automation_task_group- IT automation task groupscrowdstrike_it_automation_policy- IT automation policies
- Create
sweep.goin the service package (e.g.,internal/host_groups/sweep.go) - Implement
RegisterSweepers()function - Add sweeper registration to
internal/sweep/sweep_test.go
Example:
package myservice
import (
"github.com/hashicorp/terraform-provider-crowdstrike/internal/sweep"
)
func RegisterSweepers() {
sweep.Register("crowdstrike_my_resource", sweepMyResources,
"crowdstrike_dependency", // Optional dependencies
)
}
func sweepMyResources(ctx context.Context, client *client.CrowdStrikeAPISpecification) ([]sweep.Sweepable, error) {
// Implementation
}Sweepers can declare dependencies to ensure cleanup order:
sweep.Register("crowdstrike_policy_attachment", sweepAttachments)
sweep.Register("crowdstrike_policy", sweepPolicies,
"crowdstrike_policy_attachment", // Delete attachments first
)internal/sweep/sweep.go- Core interfaces (Sweepable), shared client, and orchestrationinternal/sweep/register.go- Registration helper that wraps sweepers with error handlinginternal/sweep/resource.go- Resource wrapper for creating sweepable resourcesinternal/sweep/skip.go- Error handling logic for skipping transient failuresinternal/sweep/sweep_test.go- TestMain entry point and sweeper registration
Each service package can implement a sweep.go file that:
- Defines a
RegisterSweepers()function - Implements sweep functions that list and filter test resources
- Returns a list of
Sweepableresources to delete
The SweepOrchestrator uses hashicorp/go-multierror to delete resources in parallel while collecting errors. All resources within a sweeper are deleted concurrently unless errors occur.
Sweepers skip transient errors that shouldn't fail the entire sweep:
- Rate limiting (429)
- Service unavailable (503)
- Timeouts
- Network errors
- Resource not found (404)
Test resources are identified by the sweep.ResourcePrefix constant in their name field:
if !strings.HasPrefix(name, sweep.ResourcePrefix) {
log.Printf("[INFO] Skipping resource %s (not a test resource)", name)
continue
}Each service implements a delete function:
func deleteResource(ctx context.Context, client *client.CrowdStrikeAPISpecification, id string) error {
params := service.NewDeleteResourceParams()
params.WithContext(ctx)
params.Ids = []string{id}
_, err := client.Service.DeleteResource(params)
if err != nil {
if sweep.ShouldIgnoreError(err) {
sweep.Debug("Ignoring error for resource %s: %s", id, err)
return nil
}
return err
}
return nil
}Rate limit errors are automatically skipped. If you see consistent rate limiting, you can:
- Wait and re-run the sweeper
- Run sweepers for specific resources instead of all at once
Verify that:
- Resources use the
sweep.ResourcePrefixconstant (accessed viaacctest.ResourcePrefixin tests) - The sweeper is registered in
internal/sweep/sweep_test.go - The list API call is returning the resources
Increase the timeout:
make sweep SWEEP_TIMEOUT=120mThe sweep infrastructure can be tested by:
- Creating test resources manually
- Running the sweeper
- Verifying resources are deleted
Example:
# Create a test host group via Terraform
cd examples/resources/crowdstrike_host_group
terraform apply
# Run the sweeper
make sweep
# Verify the resource was deleted
terraform plan # Should show resource needs to be createdWhen adding a new sweeper, consider if other resources must be deleted first:
- Attachments before policies
- Policies before the resources they protect
- Child resources before parent resources
Declare dependencies in the Register() call:
sweep.Register("crowdstrike_child", sweepChildren)
sweep.Register("crowdstrike_parent", sweepParents,
"crowdstrike_child", // Delete children first
)