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

Add Terraform support for watsonx.governance service #162

Merged
merged 12 commits into from
Apr 25, 2024
6 changes: 3 additions & 3 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
go-version: 1.19

- name: Run golangci-lint
uses: golangci/golangci-lint-action@v2.5.2
uses: golangci/golangci-lint-action@v2.297.0
with:
# Required: the version of golangci-lint is required and must be specified without patch version: they always use the latest patch version.
version: v1.45
version: latest
skip-pkg-cache: true
args: --timeout 3m0s

- name: Install Terragrunt v0.31.8
Expand Down
8 changes: 8 additions & 0 deletions infracost-usage-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ resource_type_default_usage:
wd_collections: 301
scc_evaluations: 1
data-science-experience_CAPACITY_UNIT_HOURS: 1
aiopenscale_RESOURCE_UNITS: 1
aiopenscale_MODELS_PER_MONTH: 1
ibm_tg_gateway:
connection: 3
data_transfer_global: 1000
Expand Down Expand Up @@ -1335,6 +1337,12 @@ resource_usage:
ibm_resource_instance.watson_studio_professional:
data-science-experience_CAPACITY_UNIT_HOURS: 1 # Amount of Capacity Unit-Hours used in a month

ibm_resource_instance.watson_governance_essentials:
aiopenscale_RESOURCE_UNITS: 1

ibm_resource_instance.watson_governance_standard_v2:
aiopenscale_MODELS_PER_MONTH: 1

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
Expand Down
3 changes: 3 additions & 0 deletions internal/providers/terraform/ibm/ibm.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ var globalCatalogServiceId = map[string]catalogMetadata{
"wx": {"51c53b72-918f-4869-b834-2d99eb28422a", []string{}, nil},
"conversation": {"7045626d-55e3-4418-be11-683a26dbc1e5", []string{}, nil},
"aiopenscale": {"2ad019f3-0fd6-4c25-966d-f3952481a870", []string{}, nil},
"sysdig-monitor": {"090c2c10-8c38-11e8-bec2-493df9c49eb8", []string{}, nil},
"sysdig-secure": {"e831e900-82d6-11ec-95c5-c12c5a5d9687", []string{}, nil},
"logdna": {"e13e1860-959c-11e8-871e-ad157af61ad7", []string{}, nil},
}

func SetCatalogMetadata(d *schema.ResourceData, resourceType string, config map[string]any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@
├─ Additional Monthly Documents 1,000 Documents $50.00
└─ Additional Monthly Queries 1,000 Queries $20.00

ibm_resource_instance.watson_governance_essentials
└─ Resource Units 100 RU $60.00

ibm_resource_instance.watson_governance_lite
└─ Lite plan 1 $0.00

ibm_resource_instance.watson_governance_standard_v2
└─ Deployed Models 1 Model $261.00

ibm_resource_instance.watson_studio_lite
└─ Lite plan 1 $0.00

Expand All @@ -139,7 +148,7 @@
├─ Class 2 Resource Units 50 RU $0.09
└─ Class 3 Resource Units 50 RU $0.25

OVERALL TOTAL $15,470.56
OVERALL TOTAL $15,791.56
──────────────────────────────────
32 cloud resources were detected:
32 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
35 cloud resources were detected:
35 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,33 @@ resource "ibm_resource_instance" "watson_studio_professional" {
}

resource "ibm_resource_instance" "watson_studio_lite" {
name = "ws_lie"
name = "ws_lite"
service = "data-science-experience"
plan = "free-v1"
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "watson_governance_lite" {
name = "wgov_lite"
service = "aiopenscale"
plan = "lite"
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "watson_governance_essentials" {
name = "wgov_essentials"
service = "aiopenscale"
plan = "essentials"
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "watson_governance_standard_v2" {
name = "wgov_standard_v2"
service = "aiopenscale"
plan = "standard-v2"
location = "us-south"
resource_group_id = "default"
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,11 @@ resource_usage:

ibm_resource_instance.watson_studio_lite:
data-science-experience_CAPACITY_UNIT_HOURS: 10

ibm_resource_instance.watson_governance_essentials:
aiopenscale_RESOURCE_UNITS: 100

ibm_resource_instance.watson_governance_standard_v2:
aiopenscale_MODELS_PER_MONTH: 2


6 changes: 6 additions & 0 deletions internal/resources/ibm/resource_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ type ResourceInstance struct {
SCC_Evaluations *float64 `infracost_usage:"scc_evaluations"`
// Watson Studio
WS_CUH *float64 `infracost_usage:"data-science-experience_CAPACITY_UNIT_HOURS"`
// Watson.governance
WGOV_ru *float64 `infracost_usage:"aiopenscale_RESOURCE_UNITS"`
WGOV_Models *float64 `infracost_usage:"aiopenscale_MODELS_PER_MONTH"`
}

type ResourceCostComponentsFunc func(*ResourceInstance) []*schema.CostComponent
Expand Down Expand Up @@ -122,6 +125,8 @@ var ResourceInstanceUsageSchema = []*schema.UsageItem{
{Key: "wd_collections", DefaultValue: 0, ValueType: schema.Float64},
{Key: "scc_evaluations", DefaultValue: 0, ValueType: schema.Float64},
{Key: "data-science-experience_CAPACITY_UNIT_HOURS", DefaultValue: 1, ValueType: schema.Float64},
{Key: "aiopenscale_RESOURCE_UNITS", DefaultValue: 1, ValueType: schema.Float64},
{Key: "aiopenscale_MODELS_PER_MONTH", DefaultValue: 1, ValueType: schema.Float64},
}

var ResourceInstanceCostMap map[string]ResourceCostComponentsFunc = map[string]ResourceCostComponentsFunc{
Expand All @@ -139,6 +144,7 @@ var ResourceInstanceCostMap map[string]ResourceCostComponentsFunc = map[string]R
"discovery": GetWDCostComponents,
"compliance": GetSCCCostComponents,
"data-science-experience": GetWSCostComponents,
"aiopenscale": GetWGOVCostComponents,
}

func KMSKeyVersionsFreeCostComponent(r *ResourceInstance) *schema.CostComponent {
Expand Down
104 changes: 104 additions & 0 deletions internal/resources/ibm/resource_instance_aiopenscale.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package ibm

import (
"fmt"

"github.com/infracost/infracost/internal/schema"
"github.com/shopspring/decimal"
)

/**
* Lite: 'lite' (Free)
* Essentials: 'essentials'
* Standard V2 == 'standard-v2'
*/
func GetWGOVCostComponents(r *ResourceInstance) []*schema.CostComponent {
if r.Plan == "essentials" {
return []*schema.CostComponent{
WGOVResourceUnitsCostComponent(r),
}
} else if r.Plan == "standard-v2" {
return []*schema.CostComponent{
WGOVModelCostComponent(r),
}
} else if r.Plan == "lite" {
costComponent := &schema.CostComponent{
Name: "Lite plan",
UnitMultiplier: decimal.NewFromInt(1),
MonthlyQuantity: decimalPtr(decimal.NewFromInt(1)),
}
costComponent.SetCustomPrice(decimalPtr(decimal.NewFromInt(0)))
return []*schema.CostComponent{costComponent}
} else {
costComponent := schema.CostComponent{
Name: fmt.Sprintf("Plan %s with customized pricing", r.Plan),
UnitMultiplier: decimal.NewFromInt(1),
MonthlyQuantity: decimalPtr(decimal.NewFromInt(1)),
}
costComponent.SetCustomPrice(decimalPtr(decimal.NewFromInt(0)))
return []*schema.CostComponent{
&costComponent,
}
}
}

/**
* 1 RU for every:
* 1 WGOV_PredictiveModelEvals
* 1 WGOV_FoundationalModelEvals
* 1 WGOV_GlobalExplanations
* 500 WGOV_LocalExplanations
* basically, everything converts into an RU for charging costs, with limits
*/
func WGOVResourceUnitsCostComponent(r *ResourceInstance) *schema.CostComponent {
var q *decimal.Decimal
if r.WGOV_ru != nil {
q = decimalPtr(decimal.NewFromFloat(*r.WGOV_ru))
}
return &schema.CostComponent{
Name: "Resource Units",
Unit: "RU",
UnitMultiplier: decimal.NewFromInt(1),
MonthlyQuantity: q,
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("RESOURCE_UNITS"),
},
}
}

/**
* No restrictions with unlimited evaluations performed on a model, charged on a per model basis instead
*/
func WGOVModelCostComponent(r *ResourceInstance) *schema.CostComponent {
var q *decimal.Decimal
if r.WGOV_Models != nil {
q = decimalPtr(decimal.NewFromFloat(*r.WGOV_Models))
} else {
q = decimalPtr(decimal.NewFromInt(1))
}
return &schema.CostComponent{
Name: "Deployed Models",
Unit: "Model",
UnitMultiplier: decimal.NewFromInt(1),
MonthlyQuantity: q,
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("MODELS_PER_MONTH"),
},
}
}
Loading