internal/scanners/cost.go (91 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package scanners import ( "fmt" "time" "github.com/Azure/azqr/internal/models" "github.com/Azure/azqr/internal/to" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/costmanagement/armcostmanagement" "github.com/rs/zerolog/log" ) // CostScanner - Cost scanner type CostScanner struct { config *models.ScannerConfig client *armcostmanagement.QueryClient } // Init - Initializes the Cost Scanner func (s *CostScanner) Init(config *models.ScannerConfig) error { s.config = config var err error s.client, err = armcostmanagement.NewQueryClient(config.Cred, config.ClientOptions) if err != nil { return err } return nil } // QueryCosts - Query Costs. func (s *CostScanner) QueryCosts() (*models.CostResult, error) { models.LogSubscriptionScan(s.config.SubscriptionID, "Costs") timeframeType := armcostmanagement.TimeframeTypeCustom etype := armcostmanagement.ExportTypeActualCost toTime := time.Now().UTC() fromTime := time.Date(toTime.Year(), toTime.Month()-3, 1, 0, 0, 0, 0, time.UTC) sum := armcostmanagement.FunctionTypeSum dimension := armcostmanagement.QueryColumnTypeDimension qd := armcostmanagement.QueryDefinition{ Type: &etype, Timeframe: &timeframeType, TimePeriod: &armcostmanagement.QueryTimePeriod{ From: &fromTime, To: &toTime, }, Dataset: &armcostmanagement.QueryDataset{ // Granularity: &daily, Aggregation: map[string]*armcostmanagement.QueryAggregation{ "TotalCost": { Name: to.Ptr("Cost"), Function: &sum, }, }, Grouping: []*armcostmanagement.QueryGrouping{ { Name: to.Ptr("ServiceName"), Type: &dimension, }, }, }, } resp, err := s.client.Usage(s.config.Ctx, fmt.Sprintf("/subscriptions/%s", s.config.SubscriptionID), qd, nil) if err != nil { return nil, err } result := models.CostResult{ From: fromTime, To: toTime, Items: []*models.CostResultItem{}, } for _, v := range resp.Properties.Rows { result.Items = append(result.Items, &models.CostResultItem{ SubscriptionID: s.config.SubscriptionID, SubscriptionName: s.config.SubscriptionName, ServiceName: fmt.Sprintf("%v", v[1]), Value: fmt.Sprintf("%v", v[0]), Currency: fmt.Sprintf("%v", v[2]), }) } return &result, nil } func (s *CostScanner) Scan(scan bool, config *models.ScannerConfig) *models.CostResult { costResult := &models.CostResult{ Items: []*models.CostResultItem{}, } if scan { err := s.Init(config) if err != nil { log.Fatal().Err(err).Msg("Failed to initialize Cost Scanner") } costs, err := s.QueryCosts() if err != nil && !models.ShouldSkipError(err) { log.Fatal().Err(err).Msg("Failed to query costs") } costResult.From = costs.From costResult.To = costs.To costResult.Items = append(costResult.Items, costs.Items...) } return costResult }