// 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 }
// this is a copy of the method from events.go EXCEPT // that it triggers whether or not the state was updated this run func (e *ReaperEventConfig) shouldTriggerFor(r Reapable) bool { if e.DryRun { if log.Extras() { log.Info("DryRun: Not triggering %s for %s", e.Name, r.ReapableDescriptionTiny()) } return false } triggering := false // if the reapable's state is set to trigger this EventReporter for _, trigger := range e.parseTriggers() { // if the reapable's state should trigger this event if trigger == r.ReaperState().State { triggering = true } } return triggering }
// newEvent is a method of EventReporter // newEvent reports an event to Datadog func (e *DatadogEvents) newEvent(title string, text string, fields map[string]string, tags []string) error { if e.Config.DryRun { if log.Extras() { log.Info("DryRun: Not reporting %s", title) } return nil } g, err := e.godspeed() if err != nil { return err } err = g.Event(title, text, fields, tags) if err != nil { return err } return nil }