// matchesFilters applies the relevant filter groups to a filterable func matchesFilters(filterable filters.Filterable) bool { // recover from potential panics caused by malformed filters defer func() { if r := recover(); r != nil { log.Error("Recovered in matchesFilters with panic: ", r) } }() var groups map[string]filters.FilterGroup switch filterable.(type) { case *reaperaws.Instance: groups = config.Instances.FilterGroups case *reaperaws.AutoScalingGroup: groups = config.AutoScalingGroups.FilterGroups case *reaperaws.Cloudformation: groups = config.Cloudformations.FilterGroups case *reaperaws.SecurityGroup: groups = config.SecurityGroups.FilterGroups case *reaperaws.Volume: groups = config.Volumes.FilterGroups default: log.Warning("You probably screwed up and need to make sure matchesFilters works!") return false } matched := false // if there are no filters groups defined default to not match if len(groups) == 0 { return false } shouldFilter := false for _, group := range groups { if len(group) > 0 { // there is a filter shouldFilter = true } } // no filters, default to not match if !shouldFilter { return false } for name, group := range groups { didMatch := filters.ApplyFilters(filterable, group) if didMatch { matched = true filterable.AddFilterGroup(name, group) } } // convenient if isWhitelisted(filterable) { matched = false } return matched }
// newReapableEvent is a method of EventReporter func (e *Tagger) newReapableEvent(r Reapable, tags []string) error { if r.ReaperState().Until.IsZero() { log.Warning("Uninitialized time value for %s!", r.ReapableDescription()) } if e.Config.shouldTriggerFor(r) { log.Info("Tagging %s with %s", r.ReapableDescriptionTiny(), r.ReaperState().State.String()) _, err := r.Save(r.ReaperState()) if err != nil { return err } } return nil }
// cloudformationResources returns a chan of CloudformationResources, sourced from the AWS API // there is rate limiting in the AWS API for CloudformationResources, so we delay // this is skippable with the CLI flag -withoutCloudformationResources func cloudformationResources(region, id string) chan *cloudformation.StackResource { ch := make(chan *cloudformation.StackResource) if config.WithoutCloudformationResources { close(ch) return ch } api := cloudformation.New(sess, aws.NewConfig().WithRegion(region)) go func() { <-timeout // this query can fail, so we retry didRetry := false input := &cloudformation.DescribeStackResourcesInput{StackName: &id} // initial query resp, err := api.DescribeStackResources(input) for err != nil { sleepTime := 2*time.Second + time.Duration(rand.Intn(2000))*time.Millisecond if err != nil { // this error is annoying and will come up all the time... so you can disable it if strings.Split(err.Error(), ":")[0] == "Throttling" && log.Extras() { log.Warning("StackResources: %s (retrying %s after %ds)", err.Error(), id, sleepTime*1.0/time.Second) } else if strings.Split(err.Error(), ":")[0] != "Throttling" { // any other errors log.Error(fmt.Sprintf("StackResources: %s (retrying %s after %ds)", err.Error(), id, sleepTime*1.0/time.Second)) } } // wait a random amount of time... hopefully long enough to beat rate limiting time.Sleep(sleepTime) // retry query resp, err = api.DescribeStackResources(input) didRetry = true } if didRetry && log.Extras() { log.Info("Retry succeeded for %s!", id) } for _, resource := range resp.StackResources { ch <- resource } close(ch) }() return ch }
func (e *EventReporterConfig) parseTriggers() (triggers []state.StateEnum) { for _, t := range e.Triggers { switch t { case "first": triggers = append(triggers, state.FirstState) case "second": triggers = append(triggers, state.SecondState) case "third": triggers = append(triggers, state.ThirdState) case "final": triggers = append(triggers, state.FinalState) case "ignore": triggers = append(triggers, state.IgnoreState) default: log.Warning("%s is not an available EventReporter trigger", t) } } return }
// Owner extracts useful information out of the Owner tag which should // be parsable by mail.ParseAddress func (a *Resource) Owner() *mail.Address { // properly formatted email if addr, err := mail.ParseAddress(a.Tag("Owner")); err == nil { return addr } // username -> default email host email address if addr, err := mail.ParseAddress(fmt.Sprintf("%s@%s", a.Tag("Owner"), config.DefaultEmailHost)); a.Tagged("Owner") && config.DefaultEmailHost != "" && err == nil { return addr } // default owner is specified if addr, err := mail.ParseAddress( fmt.Sprintf("%s@%s", config.DefaultOwner, config.DefaultEmailHost)); config.DefaultOwner != "" && config.DefaultEmailHost != "" && err == nil { return addr } log.Warning("No default owner or email host.") return nil }