Skip to content

Commit

Permalink
add support for watson assistant
Browse files Browse the repository at this point in the history
  • Loading branch information
hiltol committed Apr 18, 2024
1 parent 98c4434 commit 804e3e5
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 8 deletions.
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"),
},
}
}

0 comments on commit 804e3e5

Please sign in to comment.