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.
Added support for databases-for-postgresql
- Loading branch information
1 parent
c738113
commit dc75564
Showing
7 changed files
with
321 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ibm | ||
|
||
import ( | ||
"github.com/infracost/infracost/internal/resources/ibm" | ||
"github.com/infracost/infracost/internal/schema" | ||
) | ||
|
||
func getDatabaseRegistryItem() *schema.RegistryItem { | ||
return &schema.RegistryItem{ | ||
Name: "ibm_database", | ||
RFunc: newDatabase, | ||
} | ||
} | ||
|
||
func newDatabase(d *schema.ResourceData, u *schema.UsageData) *schema.Resource { | ||
plan := d.Get("plan").String() | ||
location := d.Get("location").String() | ||
service := d.Get("service").String() | ||
name := d.Get("name").String() | ||
|
||
r := &ibm.Database{ | ||
Name: name, | ||
Address: d.Address, | ||
Service: service, | ||
Plan: plan, | ||
Location: location, | ||
Group: d.RawValues, | ||
} | ||
r.PopulateUsage(u) | ||
|
||
configuration := make(map[string]any) | ||
configuration["service"] = service | ||
configuration["plan"] = plan | ||
configuration["location"] = location | ||
|
||
SetCatalogMetadata(d, service, 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 TestDatabase(t *testing.T) { | ||
t.Parallel() | ||
if testing.Short() { | ||
t.Skip("skipping test in short mode") | ||
} | ||
|
||
tftest.GoldenFileResourceTests(t, "database_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
16 changes: 16 additions & 0 deletions
16
internal/providers/terraform/ibm/testdata/database_test/database_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,16 @@ | ||
|
||
Name Monthly Qty Unit Monthly Cost | ||
|
||
ibm_database.test_db1 | ||
├─ RAM 24 GB-RAM $129.36 | ||
├─ Disk 256 GB-DISK $161.28 | ||
└─ Core 6 Virtual Processor Core $193.80 | ||
|
||
ibm_database.test_db2 | ||
├─ RAM 60 GB-RAM $323.40 | ||
└─ Disk 20 GB-DISK $12.60 | ||
|
||
OVERALL TOTAL $820.44 | ||
────────────────────────────────── | ||
2 cloud resources were detected: | ||
∙ 2 were estimated |
50 changes: 50 additions & 0 deletions
50
internal/providers/terraform/ibm/testdata/database_test/database_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,50 @@ | ||
|
||
terraform { | ||
required_providers { | ||
ibm = { | ||
source = "IBM-Cloud/ibm" | ||
version = "1.61.0" | ||
} | ||
} | ||
} | ||
|
||
provider "ibm" { | ||
region = "us-south" | ||
} | ||
|
||
resource "ibm_database" "test_db1" { | ||
name = "demo-postgres" | ||
service = "databases-for-postgresql" | ||
plan = "standard" | ||
location = "eu-gb" | ||
|
||
group { | ||
group_id = "member" | ||
memory { | ||
allocation_mb = 12288 | ||
} | ||
disk { | ||
allocation_mb = 131072 | ||
} | ||
cpu { | ||
allocation_count = 3 | ||
} | ||
} | ||
} | ||
|
||
resource "ibm_database" "test_db2" { | ||
name = "demo-postgres2" | ||
service = "databases-for-postgresql" | ||
plan = "standard" | ||
location = "eu-gb" | ||
|
||
group { | ||
group_id = "member" | ||
memory { | ||
allocation_mb = 15360 | ||
} | ||
members { | ||
allocation_count = 4 | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
internal/providers/terraform/ibm/testdata/database_test/database_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,9 @@ | ||
version: 0.1 | ||
resource_usage: | ||
ibm_database.test_db1: | ||
database_ram_mb: 12288 | ||
database_disk_mb: 131072 | ||
database_core: 3 | ||
ibm_database.test_db2: | ||
database_ram_mb: 15360 | ||
database_members: 4 |
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,190 @@ | ||
package ibm | ||
|
||
import ( | ||
"github.com/infracost/infracost/internal/resources" | ||
"github.com/infracost/infracost/internal/schema" | ||
"github.com/shopspring/decimal" | ||
"github.com/tidwall/gjson" | ||
) | ||
|
||
// Database struct represents a database instance | ||
// | ||
// This terraform resource is opaque and can handle multiple databases, provided with the right parameters | ||
type Database struct { | ||
Name string | ||
Address string | ||
Service string | ||
Plan string | ||
Location string | ||
Group gjson.Result | ||
|
||
// Databases For PostgreSQL | ||
// Catalog Link: https://cloud.ibm.com/catalog/services/databases-for-postgresql | ||
// Pricing Link: https://cloud.ibm.com/docs/databases-for-postgresql?topic=databases-for-postgresql-pricing | ||
RAM *int64 `infracost_usage:"database_ram_mb"` | ||
Disk *int64 `infracost_usage:"database_disk_mb"` | ||
Core *int64 `infracost_usage:"database_core"` | ||
Members *int64 `infracost_usage:"database_members"` | ||
} | ||
|
||
type DatabaseCostComponentsFunc func(*Database) []*schema.CostComponent | ||
|
||
// PopulateUsage parses the u schema.UsageData into the Database. | ||
// It uses the `infracost_usage` struct tags to populate data into the Database. | ||
func (r *Database) PopulateUsage(u *schema.UsageData) { | ||
resources.PopulateArgsWithUsage(r, u) | ||
} | ||
|
||
// DatabaseUsageSchema defines a list which represents the usage schema of Database. | ||
var DatabaseUsageSchema = []*schema.UsageItem{ | ||
{Key: "database_ram_mb", DefaultValue: 0, ValueType: schema.Int64}, | ||
{Key: "database_disk_mb", DefaultValue: 0, ValueType: schema.Int64}, | ||
{Key: "database_core", DefaultValue: 0, ValueType: schema.Int64}, | ||
{Key: "database_members", DefaultValue: 0, ValueType: schema.Int64}, | ||
} | ||
|
||
var DatabaseCostMap map[string]DatabaseCostComponentsFunc = map[string]DatabaseCostComponentsFunc{ | ||
"databases-for-postgresql": GetPostgresCostComponents, | ||
// "databases-for-etcd": | ||
// "databases-for-redis": | ||
// "databases-for-elasticsearch": | ||
// "messages-for-rabbitmq": | ||
// "databases-for-mongodb": | ||
// "databases-for-mysql": | ||
// "databases-for-cassandra": | ||
// "databases-for-enterprisedb" | ||
} | ||
|
||
func ConvertMBtoGB(d decimal.Decimal) decimal.Decimal { | ||
return d.Div(decimal.NewFromInt(1024)) | ||
} | ||
|
||
func PostgresRAMCostComponent(r *Database) *schema.CostComponent { | ||
var R decimal.Decimal | ||
if r.RAM != nil { | ||
R = ConvertMBtoGB(decimal.NewFromInt(*r.RAM)) | ||
} else { // set the default | ||
R = decimal.NewFromInt(1) | ||
} | ||
var m decimal.Decimal | ||
if r.Members != nil { | ||
m = decimal.NewFromInt(*r.Members) | ||
} else { // set the default | ||
m = decimal.NewFromInt(2) | ||
} | ||
|
||
cost := R.Mul(m) | ||
|
||
costComponent := schema.CostComponent{ | ||
Name: "RAM", | ||
Unit: "GB-RAM", | ||
MonthlyQuantity: &cost, | ||
UnitMultiplier: decimal.NewFromInt(1), | ||
ProductFilter: &schema.ProductFilter{ | ||
VendorName: strPtr("ibm"), | ||
Region: strPtr(r.Location), | ||
Service: strPtr("databases-for-postgresql"), | ||
ProductFamily: strPtr("service"), | ||
}, | ||
PriceFilter: &schema.PriceFilter{ | ||
Unit: strPtr("GIGABYTE_MONTHS_RAM"), | ||
}, | ||
} | ||
return &costComponent | ||
} | ||
|
||
func PostgresDiskCostComponent(r *Database) *schema.CostComponent { | ||
var d decimal.Decimal | ||
if r.Disk != nil { | ||
d = ConvertMBtoGB(decimal.NewFromInt(*r.Disk)) | ||
} else { // set the default | ||
d = decimal.NewFromInt(5) | ||
} | ||
var m decimal.Decimal | ||
if r.Members != nil { | ||
m = decimal.NewFromInt(*r.Members) | ||
} else { // set the default | ||
m = decimal.NewFromInt(2) | ||
} | ||
|
||
cost := d.Mul(m) | ||
|
||
costComponent := schema.CostComponent{ | ||
Name: "Disk", | ||
Unit: "GB-DISK", | ||
MonthlyQuantity: &cost, | ||
UnitMultiplier: decimal.NewFromInt(1), | ||
ProductFilter: &schema.ProductFilter{ | ||
VendorName: strPtr("ibm"), | ||
Region: strPtr(r.Location), | ||
Service: strPtr("databases-for-postgresql"), | ||
ProductFamily: strPtr("service"), | ||
}, | ||
PriceFilter: &schema.PriceFilter{ | ||
Unit: strPtr("GIGABYTE_MONTHS_DISK"), | ||
}, | ||
} | ||
return &costComponent | ||
} | ||
|
||
func PostgresCoreCostComponent(r *Database) *schema.CostComponent { | ||
var c decimal.Decimal | ||
if r.Core != nil { | ||
c = decimal.NewFromInt(*r.Core) | ||
} else { // set the default | ||
c = decimal.NewFromInt(0) | ||
} | ||
var m decimal.Decimal | ||
if r.Members != nil { | ||
m = decimal.NewFromInt(*r.Members) | ||
} else { // set the default | ||
m = decimal.NewFromInt(2) | ||
} | ||
|
||
cost := c.Mul(m) | ||
|
||
costComponent := schema.CostComponent{ | ||
Name: "Core", | ||
Unit: "Virtual Processor Core", | ||
MonthlyQuantity: &cost, | ||
UnitMultiplier: decimal.NewFromInt(1), | ||
ProductFilter: &schema.ProductFilter{ | ||
VendorName: strPtr("ibm"), | ||
Region: strPtr(r.Location), | ||
Service: strPtr("databases-for-postgresql"), | ||
ProductFamily: strPtr("service"), | ||
}, | ||
PriceFilter: &schema.PriceFilter{ | ||
Unit: strPtr("VIRTUAL_PROCESSOR_CORES"), | ||
}, | ||
} | ||
return &costComponent | ||
} | ||
|
||
func GetPostgresCostComponents(r *Database) []*schema.CostComponent { | ||
return []*schema.CostComponent{ | ||
PostgresRAMCostComponent(r), | ||
PostgresDiskCostComponent(r), | ||
PostgresCoreCostComponent(r), | ||
} | ||
} | ||
|
||
// BuildResource builds a schema.Resource from a valid Database struct. | ||
// This method is called after the resource is initialised by an IaC provider. | ||
// See providers folder for more information. | ||
func (r *Database) BuildResource() *schema.Resource { | ||
costComponentsFunc, ok := DatabaseCostMap[r.Service] | ||
|
||
if !ok { | ||
return &schema.Resource{ | ||
Name: r.Address, | ||
UsageSchema: DatabaseUsageSchema, | ||
} | ||
} | ||
|
||
return &schema.Resource{ | ||
Name: r.Address, | ||
UsageSchema: DatabaseUsageSchema, | ||
CostComponents: costComponentsFunc(r), | ||
} | ||
} |