forked from infracost/infracost
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for VPN server resource (#186)
* Add starter files * Add cost components and function calls * Update metrics names * Add default and example usage * Add unit tests
- Loading branch information
1 parent
5d757dc
commit f3c22f7
Showing
9 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package ibm | ||
|
||
import ( | ||
"github.com/infracost/infracost/internal/resources/ibm" | ||
"github.com/infracost/infracost/internal/schema" | ||
) | ||
|
||
func getIsVpnServerRegistryItem() *schema.RegistryItem { | ||
return &schema.RegistryItem{ | ||
Name: "ibm_is_vpn_server", | ||
RFunc: newIsVpnServer, | ||
} | ||
} | ||
|
||
func newIsVpnServer(d *schema.ResourceData, u *schema.UsageData) *schema.Resource { | ||
region := d.Get("region").String() | ||
r := &ibm.IsVpnServer{ | ||
Address: d.Address, | ||
Region: region, | ||
} | ||
r.PopulateUsage(u) | ||
|
||
configuration := make(map[string]any) | ||
configuration["region"] = region | ||
|
||
SetCatalogMetadata(d, d.Type, configuration) | ||
|
||
return r.BuildResource() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package ibm_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/infracost/infracost/internal/providers/terraform/tftest" | ||
) | ||
|
||
func TestIsVpnServer(t *testing.T) { | ||
t.Parallel() | ||
if testing.Short() { | ||
t.Skip("skipping test in short mode") | ||
} | ||
|
||
tftest.GoldenFileResourceTests(t, "is_vpn_server_test") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
internal/providers/terraform/ibm/testdata/is_vpn_server_test/is_vpn_server_test.golden
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Name Monthly Qty Unit Monthly Cost | ||
|
||
ibm_is_vpc.vpc | ||
├─ VPC instance 1 Instance $0.00 | ||
├─ VPC egress free allowance (first 5GB) Monthly cost depends on usage: $0.00 per GB | ||
└─ VPC egress us-south (first 9995 GB) Monthly cost depends on usage: $0.090915 per GB | ||
└─ VPC egress us-south (next 40000 GB) Monthly cost depends on usage: $0.086735 per GB | ||
└─ VPC egress us-south (next 100000 GB) Monthly cost depends on usage: $0.07315 per GB | ||
└─ VPC egress us-south (over 149995 GB) Monthly cost depends on usage: $0.05225 per GB | ||
|
||
ibm_is_vpn_server.vpn_server | ||
├─ VPN connection hours us-south 730 Hours $7.63 | ||
└─ VPN instance hours us-south 730 Hours $91.54 | ||
|
||
ibm_is_vpn_server.vpn_server_without_usage | ||
├─ VPN connection hours us-south Monthly cost depends on usage: $0.01045 per Hours | ||
└─ VPN instance hours us-south Monthly cost depends on usage: $0.13 per Hours | ||
|
||
OVERALL TOTAL $99.17 | ||
────────────────────────────────── | ||
5 cloud resources were detected: | ||
∙ 3 were estimated, 1 of which usage-based costs, see https://infracost.io/usage-file | ||
∙ 2 were free: | ||
∙ 2 x ibm_is_subnet |
53 changes: 53 additions & 0 deletions
53
internal/providers/terraform/ibm/testdata/is_vpn_server_test/is_vpn_server_test.tf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
|
||
terraform { | ||
required_providers { | ||
ibm = { | ||
source = "IBM-Cloud/ibm" | ||
version = "1.69.0" | ||
} | ||
} | ||
} | ||
|
||
provider "ibm" { | ||
region = "us-south" | ||
} | ||
|
||
resource "ibm_is_vpc" "vpc" { | ||
name = "vpc" | ||
} | ||
|
||
resource "ibm_is_subnet" "subnet_1" { | ||
name = "subnet-1" | ||
vpc = ibm_is_vpc.vpc.id | ||
zone = "us-south-1" | ||
ipv4_cidr_block = "10.240.0.0/24" | ||
} | ||
|
||
resource "ibm_is_subnet" "subnet_2" { | ||
name = "subnet-2" | ||
vpc = ibm_is_vpc.vpc.id | ||
zone = "us-south-2" | ||
ipv4_cidr_block = "10.240.0.0/24" | ||
} | ||
|
||
resource "ibm_is_vpn_server" "vpn_server" { | ||
name = "vpn-server" | ||
certificate_crn = "" | ||
client_ip_pool = "10.0.0.0/20" | ||
subnets = [ibm_is_subnet.subnet_1.id] | ||
client_authentication { | ||
method = "username" | ||
identity_provider = "iam" | ||
} | ||
} | ||
|
||
resource "ibm_is_vpn_server" "vpn_server_without_usage" { | ||
name = "vpn-server-no-usage" | ||
certificate_crn = "" | ||
client_ip_pool = "10.0.0.0/20" | ||
subnets = [ibm_is_subnet.subnet_2.id] | ||
client_authentication { | ||
method = "username" | ||
identity_provider = "iam" | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
internal/providers/terraform/ibm/testdata/is_vpn_server_test/is_vpn_server_test.usage.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
version: 0.1 | ||
resource_usage: | ||
ibm_is_vpn_server.vpn_server: | ||
is.vpn-server_CONNECTION_HOURS: 730 | ||
is.vpn-server_INSTANCE_HOURS: 730 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package ibm | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/infracost/infracost/internal/resources" | ||
"github.com/infracost/infracost/internal/schema" | ||
"github.com/shopspring/decimal" | ||
) | ||
|
||
// IsVpnServer struct represents a VPN server for IBM Cloud VPC | ||
// | ||
// Catalog information: https://cloud.ibm.com/vpc-ext/provision/vpnserver | ||
// Resource information: https://cloud.ibm.com/docs/vpc?topic=vpc-vpn-overview#client-to-site-vpn-server | ||
// Pricing information: https://www.ibm.com/cloud/vpc/pricing | ||
type IsVpnServer struct { | ||
Address string | ||
Region string | ||
MonthlyConnectionHours *float64 `infracost_usage:"is.vpn-server_CONNECTION_HOURS"` | ||
MonthlyInstanceHours *float64 `infracost_usage:"is.vpn-server_INSTANCE_HOURS"` | ||
} | ||
|
||
// IsVpnServerUsageSchema defines a list which represents the usage schema of IsVpnServer. | ||
var IsVpnServerUsageSchema = []*schema.UsageItem{ | ||
{Key: "is.vpn-server_CONNECTION_HOURS", DefaultValue: 0, ValueType: schema.Float64}, | ||
{Key: "is.vpn-server_INSTANCE_HOURS", DefaultValue: 0, ValueType: schema.Float64}, | ||
} | ||
|
||
// PopulateUsage parses the u schema.UsageData into the IsVpnServer. | ||
// It uses the `infracost_usage` struct tags to populate data into the IsVpnServer. | ||
func (r *IsVpnServer) PopulateUsage(u *schema.UsageData) { | ||
resources.PopulateArgsWithUsage(r, u) | ||
} | ||
|
||
func (r *IsVpnServer) connectionHoursCostComponent() *schema.CostComponent { | ||
var quantity *decimal.Decimal | ||
if r.MonthlyConnectionHours != nil { | ||
quantity = decimalPtr(decimal.NewFromFloat(*r.MonthlyConnectionHours)) | ||
} | ||
return &schema.CostComponent{ | ||
Name: fmt.Sprintf("VPN connection hours %s", r.Region), | ||
Unit: "Hours", | ||
UnitMultiplier: decimal.NewFromInt(1), | ||
MonthlyQuantity: quantity, | ||
ProductFilter: &schema.ProductFilter{ | ||
VendorName: strPtr("ibm"), | ||
Region: strPtr(r.Region), | ||
Service: strPtr("is.vpn-server"), | ||
AttributeFilters: []*schema.AttributeFilter{ | ||
{Key: "planName", ValueRegex: strPtr(fmt.Sprintf("/%s/i", "gen2-vpn-server"))}, | ||
}, | ||
}, | ||
PriceFilter: &schema.PriceFilter{ | ||
Unit: strPtr("CONNECTION_HOURS"), | ||
}, | ||
} | ||
} | ||
|
||
func (r *IsVpnServer) instanceHoursCostComponent() *schema.CostComponent { | ||
var quantity *decimal.Decimal | ||
if r.MonthlyInstanceHours != nil { | ||
quantity = decimalPtr(decimal.NewFromFloat(*r.MonthlyInstanceHours)) | ||
} | ||
return &schema.CostComponent{ | ||
Name: fmt.Sprintf("VPN instance hours %s", r.Region), | ||
Unit: "Hours", | ||
UnitMultiplier: decimal.NewFromInt(1), | ||
MonthlyQuantity: quantity, | ||
ProductFilter: &schema.ProductFilter{ | ||
VendorName: strPtr("ibm"), | ||
Region: strPtr(r.Region), | ||
Service: strPtr("is.vpn-server"), | ||
AttributeFilters: []*schema.AttributeFilter{ | ||
{Key: "planName", ValueRegex: strPtr(fmt.Sprintf("/%s/i", "gen2-vpn-server"))}, | ||
}, | ||
}, | ||
PriceFilter: &schema.PriceFilter{ | ||
Unit: strPtr("INSTANCE_HOURS"), | ||
}, | ||
} | ||
} | ||
|
||
// BuildResource builds a schema.Resource from a valid IsVpnServer struct. | ||
// This method is called after the resource is initialised by an IaC provider. | ||
// See providers folder for more information. | ||
func (r *IsVpnServer) BuildResource() *schema.Resource { | ||
costComponents := []*schema.CostComponent{ | ||
r.connectionHoursCostComponent(), | ||
r.instanceHoursCostComponent(), | ||
} | ||
|
||
return &schema.Resource{ | ||
Name: r.Address, | ||
UsageSchema: IsVpnServerUsageSchema, | ||
CostComponents: costComponents, | ||
} | ||
} |