Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #10 from rocketmiles/add-tag-filter
Browse files Browse the repository at this point in the history
Add option for filtering results based on tags
  • Loading branch information
rgoomar committed Jan 3, 2021
2 parents f0bc532 + a156bc4 commit b533885
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 8 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ GLOBAL OPTIONS:
--end value Second month to compare (2020-02-01) (default: "2020-10-01")
--cost-metric value Cost Metric to compare (NetAmortizedCost, UnblendedCost, etc.) (default: "NetAmortizedCost")
--service value Define a service to dig into
--tag value Tag value to filter results (app=web, env=prod, etc.)
--sort value Column to sort results on (name, start, end, delta) (default: "name")
--sort-order value Order to sort in (asc or desc) (default: "asc")
--help, -h show help (default: false)
Expand All @@ -61,11 +62,19 @@ aws-cct --cost-metric UnblendedCost
```

*Dig into EC2 costs*

You can get the string from the initial output. Simply copy the value in the "SERVICE" section and you can filter into that
```
aws-cct --service "Amazon Elastic Compute Cloud - Compute"
```

*Filter by tags*

You can get filter costs by tag, to return costs for resources that match all specified tag values.
```
aws-cct --tag app=widgetizer --tag env=production
```

*Compare Older Months*
```
aws-cct --start 2020-08-01 --end 2020-09-01
Expand Down
53 changes: 45 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ func main() {
Usage: "Define a service to dig into",
Destination: &serviceFilter,
},
&cli.StringSliceFlag{
Name: "tag",
Usage: "Tag value to filter results (app=web, env=prod, etc.)",
},
&cli.StringFlag{
Name: "sort",
Value: "name",
Expand Down Expand Up @@ -101,8 +105,10 @@ func main() {
grouping = "USAGE_TYPE"
}

firstResultsCosts := GetCosts(svc, firstMonthStart, firstMonthEnd, costMetric, grouping, serviceFilter)
secondResultsCosts := GetCosts(svc, secondMonthStart, secondMonthEnd, costMetric, grouping, serviceFilter)
tagFilters := c.StringSlice("tag")

firstResultsCosts := GetCosts(svc, firstMonthStart, firstMonthEnd, costMetric, grouping, serviceFilter, tagFilters)
secondResultsCosts := GetCosts(svc, secondMonthStart, secondMonthEnd, costMetric, grouping, serviceFilter, tagFilters)
allServiceNames := ExtractAllServiceNames(firstResultsCosts, secondResultsCosts)

type ServiceCosts struct {
Expand Down Expand Up @@ -215,16 +221,29 @@ func ExtractAllServiceNames(firstResultsCosts map[string]float64, secondResultsC
return allServiceNames
}

func GetCosts(svc *costexplorer.CostExplorer, start string, end string, costmetric string, grouping string, serviceFilter string) map[string]float64 {
var filter *costexplorer.Expression
func GetCosts(svc *costexplorer.CostExplorer, start string, end string, costmetric string, grouping string, serviceFilter string, tagFilters []string) map[string]float64 {
// Assemble filters
var filters []*costexplorer.Expression
if len(tagFilters) > 0 {
for _, tagFilter := range tagFilters {
tagParts := strings.SplitN(tagFilter, "=", 2)
if len(tagParts) == 2 {
filters = append(filters, GetTagExpression(tagParts[0], tagParts[1]))
}
}
}
if serviceFilter != "" {
filters = append(filters, GetDimensionExpression("SERVICE", serviceFilter))
}
var filter *costexplorer.Expression
if len(filters) > 1 {
filter = &costexplorer.Expression{
Dimensions: &costexplorer.DimensionValues{
Key: aws.String("SERVICE"),
Values: aws.StringSlice([]string{serviceFilter}),
},
And: filters,
}
} else if len(filters) == 1 {
filter = filters[0]
}

costInput := &costexplorer.GetCostAndUsageInput{
Filter: filter,
Granularity: aws.String("MONTHLY"),
Expand Down Expand Up @@ -268,3 +287,21 @@ func GetCosts(svc *costexplorer.CostExplorer, start string, end string, costmetr
}
return resultsCosts
}

func GetTagExpression(tag string, value string) *costexplorer.Expression {
return &costexplorer.Expression{
Tags: &costexplorer.TagValues{
Key: aws.String(tag),
Values: aws.StringSlice([]string{value}),
},
}
}

func GetDimensionExpression(dimension string, value string) *costexplorer.Expression {
return &costexplorer.Expression{
Dimensions: &costexplorer.DimensionValues{
Key: aws.String(dimension),
Values: aws.StringSlice([]string{value}),
},
}
}

0 comments on commit b533885

Please sign in to comment.