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

Refactor: migration Azure resources #2901

Merged
merged 16 commits into from
Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
196 changes: 15 additions & 181 deletions internal/providers/terraform/azure/application_gateway.go
Original file line number Diff line number Diff line change
@@ -1,197 +1,31 @@
package azure

import (
"fmt"
"strings"

"github.com/shopspring/decimal"
"github.com/tidwall/gjson"

"github.com/infracost/infracost/internal/resources/azure"
"github.com/infracost/infracost/internal/schema"
"github.com/infracost/infracost/internal/usage"
)

func GetAzureRMApplicationGatewayRegistryItem() *schema.RegistryItem {
func getApplicationGatewayRegistryItem() *schema.RegistryItem {
return &schema.RegistryItem{
Name: "azurerm_application_gateway",
RFunc: NewAzureRMApplicationGateway,
}
}

func NewAzureRMApplicationGateway(d *schema.ResourceData, u *schema.UsageData) *schema.Resource {
region := lookupRegion(d, []string{})
var monthlyDataProcessedGb *decimal.Decimal
skuName := d.Get("sku.0.name").String()
var sku, tier string
costComponents := make([]*schema.CostComponent, 0)
tierLimits := []int{10240, 30720}

var capacityUnits int64 = 1

if d.Get("autoscale_configuration.0.min_capacity").Type != gjson.Null {
capacityUnits = d.Get("autoscale_configuration.0.min_capacity").Int()
}

if u != nil && u.Get("capacity_units").Type != gjson.Null {
capacityUnits = u.Get("capacity_units").Int()
}

if d.Get("sku.0.capacity").Type != gjson.Null {
capacityUnits = d.Get("sku.0.capacity").Int()
}

skuNameParts := strings.Split(skuName, "_")
if len(skuNameParts) > 1 {
sku = strings.ToLower(skuNameParts[1])
}

if sku != "v2" {
if strings.ToLower(skuNameParts[0]) == "standard" {
tier = "basic"
} else {
tier = "WAF"
}
costComponents = append(costComponents, gatewayCostComponent(fmt.Sprintf("Gateway usage (%s, %s)", tier, sku), region, tier, sku, capacityUnits))

if u != nil && u.Get("monthly_data_processed_gb").Type != gjson.Null {
monthlyDataProcessedGb = decimalPtr(decimal.NewFromInt(u.Get("monthly_data_processed_gb").Int()))
result := usage.CalculateTierBuckets(*monthlyDataProcessedGb, tierLimits)

if sku == "small" {
if result[0].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (0-10TB)", region, sku, "0", &result[0]))
}
if result[1].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (10-40TB)", region, sku, "0", &result[1]))
}
if result[2].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (over 40TB)", region, sku, "0", &result[2]))
}
}

if sku == "medium" {
if result[1].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (10-40TB)", region, sku, "10240", &result[1]))
}
if result[2].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (over 40TB)", region, sku, "10240", &result[2]))
}
}

if sku == "large" {
if result[2].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (over 40TB)", region, sku, "40960", &result[2]))
}
}

} else {
var unknown *decimal.Decimal
costComponents = append(costComponents, dataProcessingCostComponent("Data processing (0-10TB)", region, sku, "0", unknown))
}
}

if sku == "v2" {
if strings.ToLower(skuNameParts[0]) == "standard" {
tier = "basic v2"
costComponents = append(costComponents, fixedForV2CostComponent(fmt.Sprintf("Gateway usage (%s)", tier), region, "standard v2"))
costComponents = append(costComponents, capacityUnitsCostComponent("basic", region, "standard v2", capacityUnits))
} else {
tier = "WAF v2"
costComponents = append(costComponents, fixedForV2CostComponent(fmt.Sprintf("Gateway usage (%s)", tier), region, tier))
costComponents = append(costComponents, capacityUnitsCostComponent("WAF", region, tier, capacityUnits))
}

}

return &schema.Resource{
Name: d.Address,
CostComponents: costComponents,
RFunc: NewApplicationGateway,
}
}

func gatewayCostComponent(name, region, tier, sku string, capacityUnits int64) *schema.CostComponent {
return &schema.CostComponent{
Name: name,
Unit: "hours",
UnitMultiplier: decimal.NewFromInt(1),
HourlyQuantity: decimalPtr(decimal.NewFromInt(capacityUnits)),
ProductFilter: &schema.ProductFilter{
VendorName: strPtr("azure"),
Region: strPtr(region),
Service: strPtr("Application Gateway"),
ProductFamily: strPtr("Networking"),
AttributeFilters: []*schema.AttributeFilter{
{Key: "productName", ValueRegex: regexPtr(fmt.Sprintf("%s Application Gateway$", tier))},
{Key: "meterName", ValueRegex: regexPtr(fmt.Sprintf("%s Gateway$", sku))},
},
},
PriceFilter: &schema.PriceFilter{
PurchaseOption: strPtr("Consumption"),
},
}
}
func dataProcessingCostComponent(name, region, sku, startUsage string, qty *decimal.Decimal) *schema.CostComponent {
return &schema.CostComponent{
Name: name,
Unit: "GB",
UnitMultiplier: decimal.NewFromInt(1),
MonthlyQuantity: qty,
ProductFilter: &schema.ProductFilter{
VendorName: strPtr("azure"),
Region: strPtr(region),
Service: strPtr("Application Gateway"),
ProductFamily: strPtr("Networking"),
AttributeFilters: []*schema.AttributeFilter{
{Key: "meterName", ValueRegex: regexPtr(fmt.Sprintf("%s Data Processed", sku))},
},
},
PriceFilter: &schema.PriceFilter{
PurchaseOption: strPtr("Consumption"),
StartUsageAmount: strPtr(startUsage),
},
func NewApplicationGateway(d *schema.ResourceData, u *schema.UsageData) *schema.Resource {
var autoscalingMinCapacity *int64
if d.Get("autoscale_configuration.0.min_capacity").Exists() {
autoscalingMinCapacity = intPtr(d.Get("autoscale_configuration.0.min_capacity").Int())
}
}
func capacityUnitsCostComponent(name, region, tier string, capacityUnits int64) *schema.CostComponent {
return &schema.CostComponent{
Name: fmt.Sprintf("V2 capacity units (%s)", name),
Unit: "CU",
UnitMultiplier: decimal.NewFromInt(1),
HourlyQuantity: decimalPtr(decimal.NewFromInt(capacityUnits)),
ProductFilter: &schema.ProductFilter{
VendorName: strPtr("azure"),
Region: strPtr(region),
Service: strPtr("Application Gateway"),
ProductFamily: strPtr("Networking"),
AttributeFilters: []*schema.AttributeFilter{
{Key: "productName", ValueRegex: regexPtr(fmt.Sprintf("Application Gateway %s$", tier))},
{Key: "meterName", ValueRegex: regexPtr("Capacity Units$")},
},
},

PriceFilter: &schema.PriceFilter{
PurchaseOption: strPtr("Consumption"),
},
r := &azure.ApplicationGateway{
Address: d.Address,
SKUName: d.Get("sku.0.name").String(),
SKUCapacity: d.Get("sku.0.capacity").Int(),
AutoscalingMinCapacity: autoscalingMinCapacity,
Region: lookupRegion(d, []string{}),
}
}

func fixedForV2CostComponent(name, region, tier string) *schema.CostComponent {
return &schema.CostComponent{
Name: name,
Unit: "hours",
UnitMultiplier: decimal.NewFromInt(1),
HourlyQuantity: decimalPtr(decimal.NewFromInt(1)),
ProductFilter: &schema.ProductFilter{
VendorName: strPtr("azure"),
Region: strPtr(region),
Service: strPtr("Application Gateway"),
ProductFamily: strPtr("Networking"),
AttributeFilters: []*schema.AttributeFilter{
{Key: "productName", ValueRegex: regexPtr(fmt.Sprintf("Application Gateway %s$", tier))},
{Key: "meterName", ValueRegex: regexPtr("Fixed Cost$")},
},
},
PriceFilter: &schema.PriceFilter{
PurchaseOption: strPtr("Consumption"),
},
}
r.PopulateUsage(u)
return r.BuildResource()
}
112 changes: 7 additions & 105 deletions internal/providers/terraform/azure/bastion_host.go
Original file line number Diff line number Diff line change
@@ -1,116 +1,18 @@
package azure

import (
"fmt"

"github.com/shopspring/decimal"

"github.com/infracost/infracost/internal/resources/azure"
"github.com/infracost/infracost/internal/schema"
"github.com/infracost/infracost/internal/usage"
)

func GetAzureRMBastionHostRegistryItem() *schema.RegistryItem {
func getBastionHostRegistryItem() *schema.RegistryItem {
return &schema.RegistryItem{
Name: "azurerm_bastion_host",
RFunc: NewAzureRMBastionHost,
}
}

func NewAzureRMBastionHost(d *schema.ResourceData, u *schema.UsageData) *schema.Resource {
productType := "Basic"
region := lookupRegion(d, []string{})

costComponents := []*schema.CostComponent{
{
Name: "Bastion host",
Unit: "hours",
UnitMultiplier: decimal.NewFromInt(1),
HourlyQuantity: decimalPtr(decimal.NewFromInt(1)),
ProductFilter: &schema.ProductFilter{
VendorName: strPtr("azure"),
Region: strPtr(region),
Service: strPtr("Azure Bastion"),
ProductFamily: strPtr("Networking"),
AttributeFilters: []*schema.AttributeFilter{
{Key: "skuName", Value: strPtr(productType)},
{Key: "meterName", Value: strPtr(fmt.Sprintf("%s Gateway", productType))},
},
},
PriceFilter: &schema.PriceFilter{
PurchaseOption: strPtr("Consumption"),
},
},
}

costComponents = append(costComponents, outboundDataTransferComponents(u, region, productType)...)

return &schema.Resource{
Name: d.Address,
CostComponents: costComponents,
RFunc: NewBastionHost,
}
}

func outboundDataTransferComponents(u *schema.UsageData, region, productType string) []*schema.CostComponent {
costComponents := make([]*schema.CostComponent, 0)
name := "Outbound data transfer "

type dataTier struct {
name string
startUsage string
}

data := []dataTier{
{name: fmt.Sprintf("%s%s", name, "(first 10TB)"), startUsage: "5"},
{name: fmt.Sprintf("%s%s", name, "(next 40TB)"), startUsage: "10240"},
{name: fmt.Sprintf("%s%s", name, "(next 100TB)"), startUsage: "51200"},
{name: fmt.Sprintf("%s%s", name, "(next 350TB)"), startUsage: "153600"},
{name: fmt.Sprintf("%s%s", name, "(over 500TB)"), startUsage: "512000"},
}

if u != nil && u.Get("monthly_outbound_data_gb").Exists() {
tierLimits := []int{10000, 50000, 150000, 500000}
monthlyOutboundDataGb := decimal.NewFromInt(u.Get("monthly_outbound_data_gb").Int())
tiers := usage.CalculateTierBuckets(monthlyOutboundDataGb, tierLimits)
for i, d := range data {
if i < len(tiers) && tiers[i].GreaterThan(decimal.Zero) {
costComponents = append(costComponents, outboundDataTransferSingleComponent(
d.name,
region,
productType,
d.startUsage,
decimalPtr(tiers[i])))
}
}
} else {
costComponents = append(costComponents, outboundDataTransferSingleComponent(
data[0].name,
region,
productType,
data[0].startUsage,
nil))
}
return costComponents
}

func outboundDataTransferSingleComponent(name, region, productType, startUsage string, quantity *decimal.Decimal) *schema.CostComponent {
return &schema.CostComponent{
Name: name,
Unit: "GB",
UnitMultiplier: decimal.NewFromInt(1),
MonthlyQuantity: quantity,
ProductFilter: &schema.ProductFilter{
VendorName: strPtr("azure"),
Region: strPtr(region),
Service: strPtr("Azure Bastion"),
ProductFamily: strPtr("Networking"),
AttributeFilters: []*schema.AttributeFilter{
{Key: "skuName", Value: strPtr(productType)},
{Key: "meterName", Value: strPtr(fmt.Sprintf("%s Data Transfer Out", productType))},
},
},
PriceFilter: &schema.PriceFilter{
PurchaseOption: strPtr("Consumption"),
StartUsageAmount: strPtr(startUsage),
},
}
func NewBastionHost(d *schema.ResourceData, u *schema.UsageData) *schema.Resource {
r := &azure.BastionHost{Address: d.Address, Region: lookupRegion(d, []string{})}
r.PopulateUsage(u)
return r.BuildResource()
}