diff --git a/infracost-usage-example.yml b/infracost-usage-example.yml index 059ce6b95ce..08457e68503 100644 --- a/infracost-usage-example.yml +++ b/infracost-usage-example.yml @@ -84,6 +84,17 @@ resource_type_default_usage: sysdig-secure_VM_NODE_HOUR: 501 aiopenscale_RESOURCE_UNITS: 1 aiopenscale_MODELS_PER_MONTH: 1 + dns-svcs_ITEMS: 2 # 1 zone included + dns-svcs_MILLION_ITEMS_CREXTERNALQUERIES: 11 # Tiered; 1-10, 10+ + dns-svcs_MILLION_ITEMS: 1001 # Tiered; 1-999, 999+, 1 included + dns-svcs_NUMBERGLB: 1 # Number of GLB HOURS + dns-svcs_NUMBERHEALTHCHECK: 1 + dns-svcs_NUMBERPOOLS: 1 # Number of pool HOURS + dns-svcs_RESOLVERLOCATIONS: 1 # Number of resolver location HOURS + dns-svcs_qty_custom_resolver_locations: 1 # Number of resolver locations + dns-svcs_qty_glb_instances: 1 # Number of GLBs + dns-svcs_qty_pools: 1 # Number of pools + ibm_tg_gateway: connection: 3 data_transfer_global: 1000 @@ -1351,6 +1362,17 @@ resource_usage: ibm_resource_instance.watson_governance_standard_v2: aiopenscale_MODELS_PER_MONTH: 1 + ibm_resource_instance.dns_services: + dns-svcs_MILLION_ITEMS_CREXTERNALQUERIES: 11 # Tiered; 1-10, 10+ + dns-svcs_MILLION_ITEMS: 1001 # Tiered; 1-999, 999+, 1 included + dns-svcs_NUMBERGLB: 1 # Number of GLB HOURS + dns-svcs_NUMBERHEALTHCHECK: 1 + dns-svcs_NUMBERPOOLS: 1 # Number of pool HOURS + dns-svcs_RESOLVERLOCATIONS: 1 # Number of resolver location HOURS + dns-svcs_qty_custom_resolver_locations: 1 # Number of resolver locations + dns-svcs_qty_glb_instances: 1 # Number of GLBs + dns-svcs_qty_pools: 1 # Number of pools + ibm_tg_gateway.tg_gateway: connection: 25 # Monthly number of connections to the gateway data_transfer_local: 2500 # Monthly local traffic through the gateway in GB diff --git a/internal/providers/terraform/ibm/ibm.go b/internal/providers/terraform/ibm/ibm.go index aabdb54355c..66a8e9584ba 100644 --- a/internal/providers/terraform/ibm/ibm.go +++ b/internal/providers/terraform/ibm/ibm.go @@ -86,6 +86,7 @@ var globalCatalogServiceId = map[string]catalogMetadata{ "logdnaat": {"dcc46a60-e13b-11e8-a015-757410dab16b", []string{}, nil, "https://cloud.ibm.com/catalog/services/logdnaat"}, "continuous-delivery": {"59b735ee-5938-4ebd-a6b2-541aef2d1f68", []string{}, nil, "https://cloud.ibm.com/catalog/services/continuous-delivery"}, "compliance": {"compliance", []string{}, nil, "https://cloud.ibm.com/catalog/services/security-and-compliance-center"}, + "dns-svcs": {"b4ed8a30-936f-11e9-b289-1d079699cbe5", []string{}, nil, "https://cloud.ibm.com/catalog/services/dns-services"}, } func SetCatalogMetadata(d *schema.ResourceData, resourceType string, config map[string]any) { diff --git a/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.golden b/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.golden index 9ab47333f33..212f5bd900e 100644 --- a/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.golden +++ b/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.golden @@ -7,6 +7,17 @@ ibm_resource_instance.cd_instance_professional └─ Authorized Users 2 Authorized Users $75.40 + ibm_resource_instance.dns_svcs_standard + ├─ Additional Zones 1 Zones $0.54 + ├─ Pool Hours 1 Hours $0.04 + ├─ GLB Instance Hours 1 Hours $0.04 + ├─ Health Checks 1 Health Checks $1.08 + ├─ Custom Resolver Location Hours 1 Hours $0.13 + ├─ Million Custom Resolver External Queries (first 10 Million Queries) 10 Million Queries $4.31 + ├─ Million Custom Resolver External Queries (over 10 Million Queries) 1 Million Queries $0.22 + └─ Additional Million DNS Queries (first 999 Million Queries) 999 Million Queries $645.16 + └─ Additional Million DNS Queries (over 999 Million Queries) 1 Million Queries $0.32 + ibm_resource_instance.resource_instance_activity_tracker_7day └─ Gigabyte Months 10 Gigabyte Months $16.15 @@ -168,7 +179,7 @@ ├─ Class 2 Resource Units 50 RU $0.09 └─ Class 3 Resource Units 50 RU $0.25 - OVERALL TOTAL $18,597.15 + OVERALL TOTAL $19,248.98 ────────────────────────────────── -36 cloud resources were detected: -∙ 36 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file \ No newline at end of file +37 cloud resources were detected: +∙ 37 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file \ No newline at end of file diff --git a/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.tf b/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.tf index 220e3bb49cb..12535a912e9 100644 --- a/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.tf +++ b/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.tf @@ -289,3 +289,11 @@ resource "ibm_resource_instance" "watson_governance_standard_v2" { location = "us-south" resource_group_id = "default" } + +resource "ibm_resource_instance" "dns_svcs_standard" { + name = "dns_svcs_standard" + service = "dns-svcs" + plan = "standard-dns" + location = "global" + resource_group_id = "default" +} \ No newline at end of file diff --git a/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.usage.yml b/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.usage.yml index 504819fd618..a912854f2d9 100644 --- a/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.usage.yml +++ b/internal/providers/terraform/ibm/testdata/resource_instance_test/resource_instance_test.usage.yml @@ -67,7 +67,7 @@ resource_usage: wd_instance: 1 # Number of instances used per month wd_documents: 11000 # Number of monthly documents created; 10,000 included in the Plus plan; $50 for every additional 1,000 documents. wd_queries: 11000 # Number of queries documents created; 10,000 included in the Plus plan; $20 for every additional 1,000 queries. - + ibm_resource_instance.watson_discovery_enterprise: wd_instance: 1 # Number of instances used per month wd_documents: 101000 # Number of monthly documents created; 100,000 included in the Enterprise plan; $5 for every additional 1,000 documents. @@ -97,3 +97,15 @@ resource_usage: ibm_resource_instance.watson_governance_standard_v2: aiopenscale_MODELS_PER_MONTH: 1 + + ibm_resource_instance.dns_svcs_standard: + dns-svcs_ITEMS: 2 # Linear; 1 zone included + dns-svcs_MILLION_ITEMS_CREXTERNALQUERIES: 11 # Tiered; 1-10, 10+ + dns-svcs_MILLION_ITEMS: 1001 # Tiered; 1-999, 999+, 1 included + dns-svcs_NUMBERGLB: 1 # Linear + dns-svcs_NUMBERHEALTHCHECK: 1 # Linear + dns-svcs_NUMBERPOOLS: 1 # Linear + dns-svcs_RESOLVERLOCATIONS: 1 # Linear + dns-svcs_qty_custom_resolver_locations: 1 # Number of resolver locations + dns-svcs_qty_glb_instances: 1 # Number of GLBs + dns-svcs_qty_pools: 1 # Number of pools diff --git a/internal/resources/ibm/resource_instance.go b/internal/resources/ibm/resource_instance.go index 6eee42d6fec..eefcf8e4b07 100644 --- a/internal/resources/ibm/resource_instance.go +++ b/internal/resources/ibm/resource_instance.go @@ -85,6 +85,17 @@ type ResourceInstance struct { // Watsonx.governance WGOV_ru *float64 `infracost_usage:"aiopenscale_RESOURCE_UNITS"` WGOV_Models *float64 `infracost_usage:"aiopenscale_MODELS_PER_MONTH"` + // DNS Services + DNSServices_CustomResolverExternalQueries *int64 `infracost_usage:"dns-svcs_MILLION_ITEMS_CREXTERNALQUERIES"` + DNSServices_CustomResolverLocationHours *float64 `infracost_usage:"dns-svcs_RESOLVERLOCATIONS"` + DNSServices_CustomResolverLocations *int64 `infracost_usage:"dns-svcs_qty_custom_resolver_locations"` + DNSServices_DNSQueries *int64 `infracost_usage:"dns-svcs_MILLION_ITEMS"` + DNSServices_GLBInstanceHours *float64 `infracost_usage:"dns-svcs_NUMBERGLB"` + DNSServices_GLBInstances *int64 `infracost_usage:"dns-svcs_qty_glb_instances"` + DNSServices_HealthChecks *int64 `infracost_usage:"dns-svcs_NUMBERHEALTHCHECK"` + DNSServices_PoolHours *float64 `infracost_usage:"dns-svcs_NUMBERPOOLS"` + DNSServices_Pools *int64 `infracost_usage:"dns-svcs_qty_pools"` + DNSServices_Zones *int64 `infracost_usage:"dns-svcs_ITEMS"` } type ResourceCostComponentsFunc func(*ResourceInstance) []*schema.CostComponent @@ -133,6 +144,16 @@ var ResourceInstanceUsageSchema = []*schema.UsageItem{ {Key: "sysdig-secure_VM_NODE_HOUR", DefaultValue: 0, ValueType: schema.Float64}, {Key: "aiopenscale_RESOURCE_UNITS", DefaultValue: 1, ValueType: schema.Float64}, {Key: "aiopenscale_MODELS_PER_MONTH", DefaultValue: 1, ValueType: schema.Float64}, + {Key: "dns-svcs_ITEMS", DefaultValue: 1, ValueType: schema.Int64}, + {Key: "dns-svcs_MILLION_ITEMS_CREXTERNALQUERIES", DefaultValue: 1, ValueType: schema.Int64}, + {Key: "dns-svcs_MILLION_ITEMS", DefaultValue: 1, ValueType: schema.Int64}, + {Key: "dns-svcs_NUMBERGLB", DefaultValue: 1, ValueType: schema.Float64}, + {Key: "dns-svcs_NUMBERHEALTHCHECK", DefaultValue: 1, ValueType: schema.Int64}, + {Key: "dns-svcs_NUMBERPOOLS", DefaultValue: 1, ValueType: schema.Float64}, + {Key: "dns-svcs_RESOLVERLOCATIONS", DefaultValue: 1, ValueType: schema.Float64}, + {Key: "dns-svcs_qty_custom_resolver_locations", DefaultValue: 1, ValueType: schema.Int64}, + {Key: "dns-svcs_qty_glb_instances", DefaultValue: 1, ValueType: schema.Int64}, + {Key: "dns-svcs_qty_pools", DefaultValue: 1, ValueType: schema.Int64}, } var ResourceInstanceCostMap map[string]ResourceCostComponentsFunc = map[string]ResourceCostComponentsFunc{ @@ -152,6 +173,7 @@ var ResourceInstanceCostMap map[string]ResourceCostComponentsFunc = map[string]R "data-science-experience": GetWSCostComponents, "sysdig-secure": GetSCCWPCostComponents, "aiopenscale": GetWGOVCostComponents, + "dns-svcs": GetDNSServicesCostComponents, } func KMSKeyVersionsFreeCostComponent(r *ResourceInstance) *schema.CostComponent { diff --git a/internal/resources/ibm/resource_instance_dns-svcs.go b/internal/resources/ibm/resource_instance_dns-svcs.go new file mode 100644 index 00000000000..e4cd703e495 --- /dev/null +++ b/internal/resources/ibm/resource_instance_dns-svcs.go @@ -0,0 +1,250 @@ +package ibm + +import ( + "fmt" + + "github.com/infracost/infracost/internal/schema" + "github.com/shopspring/decimal" +) + +// Graduated Tier pricing model +const DNS_SERVICES_PROGRAMMATIC_PLAN_NAME string = "standard-dns" + +func GetDNSServicesCostComponents(r *ResourceInstance) []*schema.CostComponent { + if r.Plan == DNS_SERVICES_PROGRAMMATIC_PLAN_NAME { + return []*schema.CostComponent{ + DNSServicesZonesCostComponent(r), + DNSServicesPoolsPerHourCostComponent(r), + DNSServicesGLBInstancesPerHourCostComponent(r), + DNSServicesHealthChecksCostComponent(r), + DNSServicesCustomResolverLocationsPerHourCostComponent(r), + DNSServicesMillionCustomResolverExternalQueriesCostComponent(r), + DNSServicesMillionDNSQueriesCostComponent(r), + } + } else { + costComponent := schema.CostComponent{ + Name: fmt.Sprintf("Plan %s with customized pricing", r.Plan), + UnitMultiplier: decimal.NewFromInt(1), // Final quantity for this cost component will be divided by this amount + MonthlyQuantity: decimalPtr(decimal.NewFromInt(1)), + } + costComponent.SetCustomPrice(decimalPtr(decimal.NewFromInt(0))) + return []*schema.CostComponent{ + &costComponent, + } + } +} + +// Unit: ITEMS (Linear Tier) +func DNSServicesZonesCostComponent(r *ResourceInstance) *schema.CostComponent { + + var zones_included int = 1 + var quantity *decimal.Decimal + + if r.DNSServices_Zones != nil { + additional_zones := *r.DNSServices_Zones - int64(zones_included) + if additional_zones > 0 { + quantity = decimalPtr(decimal.NewFromInt(additional_zones)) + } else { + quantity = decimalPtr(decimal.NewFromInt(0)) + } + } + + costComponent := schema.CostComponent{ + Name: "Additional Zones", + Unit: "Zones", + UnitMultiplier: decimal.NewFromFloat(1), // Final quantity for this cost component will be divided by this amount + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("ITEMS"), + }, + } + return &costComponent +} + +// Unit: NUMBERPOOLS (Linear Tier) +func DNSServicesPoolsPerHourCostComponent(r *ResourceInstance) *schema.CostComponent { + + var quantity *decimal.Decimal + + if (r.DNSServices_PoolHours != nil) && (r.DNSServices_Pools != nil) { + quantity = decimalPtr(decimal.NewFromFloat(*r.DNSServices_PoolHours * float64(*r.DNSServices_Pools))) + } + + costComponent := schema.CostComponent{ + Name: "Pool Hours", + Unit: "Hours", + UnitMultiplier: decimal.NewFromFloat(1), // Final quantity for this cost component will be divided by this amount + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("NUMBERPOOLS"), + }, + } + return &costComponent +} + +// Unit: NUMBERGLB (Linear Tier) +func DNSServicesGLBInstancesPerHourCostComponent(r *ResourceInstance) *schema.CostComponent { + + var quantity *decimal.Decimal + + if (r.DNSServices_GLBInstanceHours != nil) && (r.DNSServices_GLBInstances != nil) { + quantity = decimalPtr(decimal.NewFromFloat(*r.DNSServices_GLBInstanceHours * float64(*r.DNSServices_GLBInstances))) + } + + costComponent := schema.CostComponent{ + Name: "GLB Instance Hours", + Unit: "Hours", + UnitMultiplier: decimal.NewFromFloat(1), // Final quantity for this cost component will be divided by this amount + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("NUMBERGLB"), + }, + } + return &costComponent +} + +// Unit: NUMBERHEALTHCHECK (Linear Tier) +func DNSServicesHealthChecksCostComponent(r *ResourceInstance) *schema.CostComponent { + + var quantity *decimal.Decimal + + if r.DNSServices_HealthChecks != nil { + quantity = decimalPtr(decimal.NewFromInt(*r.DNSServices_HealthChecks)) + } + + costComponent := schema.CostComponent{ + Name: "Health Checks", + Unit: "Health Checks", + UnitMultiplier: decimal.NewFromFloat(1), // Final quantity for this cost component will be divided by this amount + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("NUMBERHEALTHCHECK"), + }, + } + return &costComponent +} + +// Unit: RESOLVERLOCATIONS (Linear Tier) +func DNSServicesCustomResolverLocationsPerHourCostComponent(r *ResourceInstance) *schema.CostComponent { + + var quantity *decimal.Decimal + + if (r.DNSServices_CustomResolverLocationHours != nil) && (r.DNSServices_CustomResolverLocations != nil) { + quantity = decimalPtr(decimal.NewFromFloat(*r.DNSServices_CustomResolverLocationHours * float64(*r.DNSServices_CustomResolverLocations))) + } + + costComponent := schema.CostComponent{ + Name: "Custom Resolver Location Hours", + Unit: "Hours", + UnitMultiplier: decimal.NewFromFloat(1), // Final quantity for this cost component will be divided by this amount + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("RESOLVERLOCATIONS"), + }, + } + return &costComponent +} + +// Unit: MILLION_ITEMS_CREXTERNALQUERIES (Graduated Tier) +func DNSServicesMillionCustomResolverExternalQueriesCostComponent(r *ResourceInstance) *schema.CostComponent { + + var quantity *decimal.Decimal + + if r.DNSServices_CustomResolverExternalQueries != nil { + quantity = decimalPtr(decimal.NewFromInt(*r.DNSServices_CustomResolverExternalQueries)) + } + + costComponent := schema.CostComponent{ + Name: "Million Custom Resolver External Queries", + Unit: "Million Queries", + UnitMultiplier: decimal.NewFromInt(1), + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("MILLION_ITEMS_CREXTERNALQUERIES"), + }, + } + return &costComponent +} + +// Unit: MILLION_ITEMS (Graduated Tier) +func DNSServicesMillionDNSQueriesCostComponent(r *ResourceInstance) *schema.CostComponent { + + var million_dns_queries_included float32 = 1 + var quantity *decimal.Decimal + + if r.DNSServices_DNSQueries != nil { + additional_million_dns_queries := *r.DNSServices_DNSQueries - int64(million_dns_queries_included) + if additional_million_dns_queries > 0 { + quantity = decimalPtr(decimal.NewFromInt(additional_million_dns_queries)) + } else { + quantity = decimalPtr(decimal.NewFromInt(0)) + } + } + + costComponent := schema.CostComponent{ + Name: "Additional Million DNS Queries", + Unit: "Million Queries", + UnitMultiplier: decimal.NewFromInt(1), + MonthlyQuantity: quantity, + ProductFilter: &schema.ProductFilter{ + VendorName: strPtr("ibm"), + Region: strPtr(r.Location), + Service: &r.Service, + AttributeFilters: []*schema.AttributeFilter{ + {Key: "planName", Value: &r.Plan}, + }, + }, + PriceFilter: &schema.PriceFilter{ + Unit: strPtr("MILLION_ITEMS"), + }, + } + return &costComponent +}