func()

in internal/graph/graph_scanner.go [230:294]


func (a AprlScanner) graphScan(ctx context.Context, graphClient *GraphQuery, rules []models.AprlRecommendation, subscriptions map[string]string) ([]models.AprlResult, error) {
	results := []models.AprlResult{}
	subs := make([]*string, 0, len(subscriptions))
	for s := range subscriptions {
		subs = append(subs, &s)
	}

	sentQueries := 0
	for _, rule := range rules {
		if rule.GraphQuery != "" {
			result := graphClient.Query(ctx, rule.GraphQuery, subs)
			if result.Data != nil {
				for _, row := range result.Data {
					m := row.(map[string]interface{})

					log.Debug().Msg(rule.GraphQuery)

					// Check if "id" is present in the map
					if _, ok := m["id"]; !ok {
						log.Warn().Msgf("Skipping result: 'id' field is missing in the response for recommendation: %s", rule.RecommendationID)
						break
					}

					subscription := models.GetSubscriptionFromResourceID(m["id"].(string))
					subscriptionName, ok := subscriptions[subscription]
					if !ok {
						subscriptionName = ""
					}

					results = append(results, models.AprlResult{
						RecommendationID:    rule.RecommendationID,
						Category:            models.RecommendationCategory(rule.Category),
						Recommendation:      rule.Recommendation,
						ResourceType:        rule.ResourceType,
						LongDescription:     rule.LongDescription,
						PotentialBenefits:   rule.PotentialBenefits,
						Impact:              models.RecommendationImpact(rule.Impact),
						Name:                to.String(m["name"]),
						ResourceID:          to.String(m["id"]),
						SubscriptionID:      subscription,
						SubscriptionName:    subscriptionName,
						ResourceGroup:       models.GetResourceGroupFromResourceID(m["id"].(string)),
						Tags:                to.String(m["tags"]),
						Param1:              to.String(m["param1"]),
						Param2:              to.String(m["param2"]),
						Param3:              to.String(m["param3"]),
						Param4:              to.String(m["param4"]),
						Param5:              to.String(m["param5"]),
						Learn:               rule.LearnMoreLink[0].Url,
						AutomationAvailable: rule.AutomationAvailable,
						Source:              rule.Source,
					})
				}
			}
			sentQueries++
			if sentQueries == 2 {
				// Staggering queries to avoid throttling. Max 10 queries each 5 seconds.
				// https://learn.microsoft.com/en-us/azure/governance/resource-graph/concepts/guidance-for-throttled-requests#staggering-queries
				time.Sleep(1 * time.Second)
			}
		}
	}

	return results, nil
}