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 support for watson assistant #163

Merged
merged 1 commit into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions infracost-usage-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ resource_type_default_usage:
wml_class1_ru: 20
wml_class2_ru: 20
wml_class3_ru: 20
wa_instance: 1
wa_monthly_active_users: 1001
wa_voice_users: 101
ibm_tg_gateway:
connection: 3
data_transfer_global: 1000
Expand Down Expand Up @@ -1296,6 +1299,9 @@ resource_usage:
wml_class1_ru: 20 # The number of resource units used for inferencing with class 1 type models where each ru is 1000 tokens
wml_class2_ru: 20 # The number of resource units used for inferencing with class 2 type models where each ru is 1000 tokens
wml_class3_ru: 20 # The number of resource units used for inferencing with class 3 type models where each ru is 1000 tokens
wa_instance: 1 # The number of instances used per month where each instance includes 1000 monthly active users
wa_monthly_active_users: 1100 # The number of monthly active users
wa_monthly_voice_users: 100 # The number of monthly active voice users

ibm_tg_gateway.tg_gateway:
connection: 25 # Monthly number of connections to the gateway
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@
├─ Additional Time series (next 9000 Time series hour) 0 Time series hour $0.00
├─ Additional Time series (next 90000 Time series hour) 0 Time series hour $0.00
├─ Additional Time series (over 100000 Time series hour) 0 Time series hour $0.00
├─ Additional Containers 1,460 Container Hours $1.09
├─ Additional Container Hours 1,460 Container Hours $1.09
├─ Additional API Calls 100,000 API Calls $1.08
└─ Base Node Hour 730 Node Hours $37.72
└─ Node Hours 730 Node Hours $37.72

ibm_resource_instance.resource_instance_monitoring_graduated_no_usage
├─ Additional Time series (first 1000 Time series hour) Monthly cost depends on usage: $0.0001195944 per Time series hour
├─ Additional Time series (next 9000 Time series hour) Monthly cost depends on usage: $0.0000747465 per Time series hour
├─ Additional Time series (next 90000 Time series hour) Monthly cost depends on usage: $0.0000448479 per Time series hour
├─ Additional Time series (over 100000 Time series hour) Monthly cost depends on usage: $0.0000298986 per Time series hour
├─ Additional Containers Monthly cost depends on usage: $0.0007474653 per Container Hours
├─ Additional Container Hours Monthly cost depends on usage: $0.0007474653 per Container Hours
├─ Additional API Calls Monthly cost depends on usage: $0.0000107635 per API Calls
└─ Base Node Hour Monthly cost depends on usage: $0.0516648 per Node Hours
└─ Node Hours Monthly cost depends on usage: $0.0516648 per Node Hours

ibm_resource_instance.resource_instance_monitoring_lite
└─ Lite plan 1 $0.00
Expand All @@ -74,6 +74,22 @@
├─ Instance 1 Instance $321.00
└─ Active Secrets 400 Secrets $86.00

ibm_resource_instance.wa_instance_enterprise
├─ Instance 1 Instance $6,000.00
├─ Additional Monthly Active Users 1 1K MAU $120.00
└─ Monthly Active Users using voice 1 1K MAU $90.00

ibm_resource_instance.wa_instance_lite
└─ Lite plan 1 $0.00

ibm_resource_instance.wa_instance_plus
├─ Instance 1 Instance $140.00
├─ Additional Monthly Active Users 10 100 MAU $140.00
└─ Monthly Active Users using voice 1 100 MAU $9.00

ibm_resource_instance.wa_instance_trial
└─ Trial 1 $0.00

ibm_resource_instance.wml_instance_essentials
├─ Capacity Unit-Hours 20 CUH $10.40
├─ Class 1 Resource Units 50 RU $0.03
Expand All @@ -89,7 +105,7 @@
├─ Class 2 Resource Units 50 RU $0.09
└─ Class 3 Resource Units 50 RU $0.25

OVERALL TOTAL $2,381.14
OVERALL TOTAL $8,880.14
──────────────────────────────────
19 cloud resources were detected:
19 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
23 cloud resources were detected:
23 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 @@ -152,3 +152,35 @@ resource "ibm_resource_instance" "wml_instance_standard" {
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "wa_instance_lite" {
name = "wa_lite"
service = "conversation"
plan = "lite"
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "wa_instance_trial" {
name = "wa_trial"
service = "conversation"
plan = "plus-trial"
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "wa_instance_plus" {
name = "wa_plus"
service = "conversation"
plan = "plus"
location = "us-south"
resource_group_id = "default"
}

resource "ibm_resource_instance" "wa_instance_enterprise" {
name = "wa_enterprise"
service = "conversation"
plan = "enterprise"
location = "us-south"
resource_group_id = "default"
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,11 @@ resource_usage:
wml_class1_ru: 50
wml_class2_ru: 50
wml_class3_ru: 50

ibm_resource_instance.wa_instance_plus:
wa_instance: 1
wa_monthly_active_users: 2000
wa_voice_users: 100
ibm_resource_instance.wa_instance_enterprise:
wa_instance: 1
wa_monthly_active_users: 51000
wa_voice_users: 1000
8 changes: 8 additions & 0 deletions internal/resources/ibm/resource_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ type ResourceInstance struct {
WML_Class1RU *float64 `infracost_usage:"wml_class1_ru"`
WML_Class2RU *float64 `infracost_usage:"wml_class2_ru"`
WML_Class3RU *float64 `infracost_usage:"wml_class3_ru"`
// Watson Assistant
WA_Instance *float64 `infracost_usage:"wa_instance"`
WA_mau *float64 `infracost_usage:"wa_monthly_active_users"`
WA_vu *float64 `infracost_usage:"wa_voice_users"`
}

type ResourceCostComponentsFunc func(*ResourceInstance) []*schema.CostComponent
Expand Down Expand Up @@ -98,6 +102,9 @@ var ResourceInstanceUsageSchema = []*schema.UsageItem{
{Key: "wml_class1_ru", DefaultValue: 0, ValueType: schema.Float64},
{Key: "wml_class2_ru", DefaultValue: 0, ValueType: schema.Float64},
{Key: "wml_class3_ru", DefaultValue: 0, ValueType: schema.Float64},
{Key: "wa_instance", DefaultValue: 0, ValueType: schema.Float64},
{Key: "wa_monthly_active_users", DefaultValue: 0, ValueType: schema.Float64},
{Key: "wa_voice_users", DefaultValue: 0, ValueType: schema.Float64},
}

var ResourceInstanceCostMap map[string]ResourceCostComponentsFunc = map[string]ResourceCostComponentsFunc{
Expand All @@ -111,6 +118,7 @@ var ResourceInstanceCostMap map[string]ResourceCostComponentsFunc = map[string]R
"sysdig-monitor": GetSysdigCostComponenets,
"continuous-delivery": GetContinuousDeliveryCostComponenets,
"pm-20": GetWMLCostComponents,
"conversation": GetWACostComponents,
}

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

import (
"fmt"
"math"

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

const ENTERPRISE_MAU_PER_INSTANCE float64 = 50000
const ENTERPRISE_ADDITIONAL_PER_1K_USERS float64 = 1000
const PLUS_MAU_PER_INSTANCE float64 = 1000
const PLUS_ADDITIONAL_PER_100_USERS float64 = 100

/*
* lite = "Lite" free plan
* Trial = "Plus free trial plan"
* Plus = "Plus pricing plan"
* Enterprise == "Enterprise pricing plan"
*/
func GetWACostComponents(r *ResourceInstance) []*schema.CostComponent {
if (r.Plan == "enterprise") || (r.Plan == "plus") {
return []*schema.CostComponent{
WAInstanceCostComponent(r),
WAMonthlyActiveUsersCostComponent(r),
WAMonthlyVoiceUsersCostComponent(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 if r.Plan == "plus-trial" {
costComponent := schema.CostComponent{
Name: "Trial",
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,
}
}
}

func WAInstanceCostComponent(r *ResourceInstance) *schema.CostComponent {
var q *decimal.Decimal
if r.WA_Instance != nil {
q = decimalPtr(decimal.NewFromFloat(*r.WA_Instance))
} else {
q = decimalPtr(decimal.NewFromInt(1))
}
return &schema.CostComponent{
Name: "Instance",
Unit: "Instance",
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("INSTANCES"),
},
}
}

func WAMonthlyActiveUsersCostComponent(r *ResourceInstance) *schema.CostComponent {
var q *decimal.Decimal
var users_per_block float64
var included_allotment float64
var unit string

if r.Plan == "enterprise" {
included_allotment = ENTERPRISE_MAU_PER_INSTANCE
users_per_block = ENTERPRISE_ADDITIONAL_PER_1K_USERS
unit = "1K MAU"
} else {
included_allotment = PLUS_MAU_PER_INSTANCE
users_per_block = PLUS_ADDITIONAL_PER_100_USERS
unit = "100 MAU"
}

// if there are more active users than the monthly allotment of users included in the instance price, then create
// a cost component for the additional users
if r.WA_mau != nil {
additional_users := *r.WA_mau - included_allotment
if additional_users > 0 {
// price for additional users charged is per 1k quantity, rounded up,
// so 1001 additional users will equal 2 blocks of additional users
q = decimalPtr(decimal.NewFromFloat(math.Ceil(additional_users / users_per_block)))
}
}

return &schema.CostComponent{
Name: "Additional Monthly Active Users",
Unit: unit,
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("ACTIVE_USERS"),
},
}
}

func WAMonthlyVoiceUsersCostComponent(r *ResourceInstance) *schema.CostComponent {
var q *decimal.Decimal
var users_per_block float64
var unit string

if r.Plan == "enterprise" {
users_per_block = ENTERPRISE_ADDITIONAL_PER_1K_USERS
unit = "1K MAU"
} else {
users_per_block = PLUS_ADDITIONAL_PER_100_USERS
unit = "100 MAU"
}

// price for voice users charged is per 1k quantity, rounded up,
// so 1001 active users that used voice will equal 2 blocks of voice users
if r.WA_vu != nil {
voice_users := math.Ceil(*r.WA_vu / users_per_block)
q = decimalPtr(decimal.NewFromFloat(voice_users))
}

return &schema.CostComponent{
Name: "Monthly Active Users using voice",
Unit: unit,
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("ACTIVE_VOICE_USERS"),
},
}
}
Loading