Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws: implement new resources #131

Merged
merged 17 commits into from
Feb 11, 2025
Merged
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
- Now HCL functions are loaded so no more errors related to functions missing
([Issue #126](https://github.com/cycloidio/terracost/issue/126))

### Added

- AWS support for `aws_cloudwatch_log_group`, `aws_cloudwatch_metric_alarm`, `aws_kms_key`, `aws_rds_cluster`, `aws_rds_cluster_instance`, `aws_s3_bucket`, `aws_s3_bucket_analytics_configuration`, `aws_s3_bucket_inventory`, `aws_secretsmanager_secret`, `aws_sqs_queue`
([Pull #131](https://github.com/cycloidio/terracost/pull/115))

## [0.5.2] _2024-11-05_

### Added
Expand Down
3 changes: 3 additions & 0 deletions aws/field/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ const (
ThroughputCapacity // Throughput capacity
FileSystemDeploymentOption // Deployment option

// CloudWatch Alarm fields
AlarmType // Alarm Type

///// Price Attributes /////
Currency // Currency
PricePerUnit // PricePerUnit
Expand Down
52 changes: 28 additions & 24 deletions aws/field/field_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 37 additions & 8 deletions aws/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,32 @@ func DefaultFilter(_ *price.WithProduct) bool {
// MinimalFilter only ingests the supported records, skipping those that would never be used.
func MinimalFilter(pp *price.WithProduct) bool {
switch pp.Product.Service {
case "AmazonCloudWatch":
return minimalFilterCloudWatch(pp)
case "AmazonEC2":
return minimalFilterEC2(pp)
case "AmazonEFS":
return true // is minimal already
case "AmazonEKS":
return true // is minimal already
case "AmazonElastiCache":
return true // is minimal already
case "AmazonFSx":
return true
case "AmazonRDS":
return minimalFilterRDS(pp)
case "AmazonS3":
return minimalFilterS3Bucket(pp)
case "AWSDataTransfer":
return true
case "AWSELB":
return true // is minimal already
case "AmazonElastiCache":
return true // is minimal already
case "AmazonCloudWatch":
case "awskms":
return true // is minimal already
case "AmazonEKS":
case "AWSQueueService":
return true // is minimal already
case "AmazonEFS":
case "AWSSecretsManager":
return true // is minimal already
case "AmazonFSx":
return true
default:
return false
}
Expand Down Expand Up @@ -60,10 +70,29 @@ func minimalFilterEC2(pp *price.WithProduct) bool {
}
}

// minimalFilterCloudWatch only ingests records of supported product families.
func minimalFilterCloudWatch(pp *price.WithProduct) bool {
switch pp.Product.Family {
case "Data Payload", "Storage Snapshot", "Alarm":
return true
default:
return false
}
}

// minimalFilterRDS only ingests RDS records of supported product families.
func minimalFilterRDS(pp *price.WithProduct) bool {
switch pp.Product.Family {
case "Database Instance", "Database Storage", "Provisioned IOPS":
case "Database Instance", "Database Storage", "Provisioned IOPS", "Serverless", "ServerlessV2", "System Operation", "Storage Snapshot", "Performance Insights":
return true
default:
return false
}
}

func minimalFilterS3Bucket(pp *price.WithProduct) bool {
switch pp.Product.Family {
case "Storage", "API Request", "Fee":
return true
default:
return false
Expand Down
3 changes: 3 additions & 0 deletions aws/ingester.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ var columnProductToIngest = map[field.Field]string{
field.StorageType: "StorageType",
field.ThroughputCapacity: "ThroughputCapacity",
field.FileSystemDeploymentOption: "Deployment_option",

// Cloudwatch alarms
field.AlarmType: "AlarmType",
}

// columnPriceToIngest is a mapping from column title to the price.Price attribute name under which the value will
Expand Down
58 changes: 57 additions & 1 deletion aws/region/regions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,77 @@ var nameToCode = map[string]Code{
"US West (Oregon)": "us-west-2",
"US West (Los Angeles)": "us-west-2-lax-1", // Included in the offer file but missing from the docs.
"Canada (Central)": "ca-central-1",
"Canada West (Calgary)": "ca-west-1",
"EU (Stockholm)": "eu-north-1",
"EU (Ireland)": "eu-west-1",
"EU (London)": "eu-west-2",
"EU (Paris)": "eu-west-3",
"EU (Frankfurt)": "eu-central-1",
"EU (Zurich)": "eu-central-2",
"EU (Milan)": "eu-south-1",
"Asia Pacific (Mumbai)": "ap-south-1",
"EU (Spain)": "eu-south-2",
"Asia Pacific (Tokyo)": "ap-northeast-1",
"Asia Pacific (Seoul)": "ap-northeast-2",
"Asia Pacific (Osaka-Local)": "ap-northeast-3",
"Asia Pacific (Singapore)": "ap-southeast-1",
"Asia Pacific (Sydney)": "ap-southeast-2",
"Asie Pacific (Jakarta)": "ap-southeast-3",
"Asia Pacific (Melbourne)": "ap-southeast-4",
"Asie Pacific (Malaysia)": "ap-southeast-5",
"Asie Pacific (Thailand)": "ap-southeast-7",
"Asia Pacific (Hong Kong)": "ap-east-1",
"Asia Pacific (Mumbai)": "ap-south-1",
"Asie Pacific (Hyderabad)": "ap-south-2",
"South America (Sao Paulo)": "sa-east-1",
"China (Beijing)": "cn-north-1",
"China (Ningxia)": "cn-northwest-1",
"AWS GovCloud (US-West)": "us-gov-west-1",
"AWS GovCloud (US-East)": "us-gov-east-1",
"Middle East (Bahrain)": "me-south-1",
"Africa (Cape Town)": "af-south-1",
"Israel (Tel Aviv)": "il-central-1",
"Middle East (UAE)": "me-central-1",
}

// Short billing Region code
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/aws-usage-report-understand.html
var codeToShortName = map[string]string{
talset marked this conversation as resolved.
Show resolved Hide resolved
"us-east-1": "US",
"us-east-2": "USE2",
"us-west-1": "USW1",
"us-west-2": "USW2",
"us-west-2-lax-1": "LAX1",
"ca-central-1": "CAN1",
"ca-west-1": "CAW1",
"eu-north-1": "EUN1",
"eu-west-1": "EU",
"eu-west-2": "EUW2",
"eu-west-3": "EUW3",
"eu-central-1": "EUC1",
"eu-central-2": "EUC2",
"eu-south-1": "EUS1",
"eu-south-2": "EUS2",
"ap-south-1": "APS3",
"ap-northeast-1": "APN1",
"ap-northeast-2": "APN2",
"ap-northeast-3": "APN3",
"ap-southeast-1": "APS1",
"ap-southeast-2": "APS2",
"ap-southeast-3": "APS3",
"ap-southeast-4": "APS6",
"ap-southeast-5": "APS7",
"ap-southeast-7": "APS9",
"ap-east-1": "APE1",
"ap-south-2": "APS5",
"sa-east-1": "SAE1",
"cn-north-1": "CNN1",
"cn-northwest-1": "CNW1",
"us-gov-west-1": "UGW1",
"us-gov-east-1": "UGE1",
"me-south-1": "MES1",
"af-south-1": "AFS1",
"il-central-1": "ILC1",
"me-central-1": "MEC1",
}

var codeToName = make(map[Code]string)
Expand All @@ -37,3 +88,8 @@ func init() {
codeToName[code] = name
}
}

// GetRegionToShortName returns the short billing Region code for a region, which is the code that AWS commonly use in UsageType for billing purposes.
func GetRegionToShortName(region string) string {
talset marked this conversation as resolved.
Show resolved Hide resolved
return codeToShortName[region]
}
9 changes: 7 additions & 2 deletions aws/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import (

// SupportedServices is a list of all AWS services that are supported by Terracost.
var supportedServices = map[string]struct{}{
"AmazonCloudWatch": {},
"AmazonEC2": {},
"AmazonEFS": {},
"AmazonEKS": {},
"AmazonElastiCache": {},
"AmazonFSx": {},
"AmazonRDS": {},
"AmazonElastiCache": {},
"AmazonCloudWatch": {},
"AmazonS3": {},
"AWSDataTransfer": {},
"AWSELB": {},
"awskms": {},
"AWSQueueService": {},
"AWSSecretsManager": {},
}

// IsServiceSupported returns true if the AWS service is valid and supported by Terracost (e.g. for ingestion.)
Expand Down
Loading