Skip to content

Commit

Permalink
Cost base price is float64
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-sva committed Jan 14, 2025
1 parent 8db7f04 commit 097d607
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 74 deletions.
12 changes: 6 additions & 6 deletions v3/pkg/apis/hobbyfarm.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,10 +595,10 @@ type CostSpec struct {
}

type CostResource struct {
Id string `json:"id"` // id of the resource
Kind string `json:"kind"` // name like VirtualMachine
BasePrice uint64 `json:"base_price"`
TimeUnit string `json:"time_unit"` // one of [seconds, minutes, hours]
CreationUnixTimestamp int64 `json:"creation_unix_timestamp"` // unix timestamp in seconds
DeletionUnixTimestamp int64 `json:"deletion_unix_timestamp,omitempty"` // unix timestamp in seconds
Id string `json:"id"` // id of the resource
Kind string `json:"kind"` // name like VirtualMachine
BasePrice float64 `json:"base_price"`
TimeUnit string `json:"time_unit"` // one of [seconds, minutes, hours]
CreationUnixTimestamp int64 `json:"creation_unix_timestamp"` // unix timestamp in seconds
DeletionUnixTimestamp int64 `json:"deletion_unix_timestamp,omitempty"` // unix timestamp in seconds
}
44 changes: 22 additions & 22 deletions v3/protos/cost/cost.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions v3/protos/cost/cost.proto
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,24 @@ service CostSvc {

message Cost {
string cost_group = 1; // name of the cost group
uint64 total = 2; // total cost for all sources
double total = 2; // total cost for all sources
repeated CostSource source = 3;
}

message CostSource {
string kind = 1; // resource kind like VirtualMachine
uint64 cost = 2; // total cost for this kind
double cost = 2; // total cost for this kind
uint64 count = 3;
}

message CreateOrUpdateCostRequest {
string cost_group = 1;
string kind = 3; // like VirtualMachine
uint64 base_price = 4;
string time_unit = 5;
string id = 6; // resource id
int64 creation_unix_timestamp = 7; // unix timestamp in seconds
optional int64 deletion_unix_timestamp = 8; // unix timestamp in seconds
string kind = 2; // like VirtualMachine
double base_price = 3;
string time_unit = 4;
string id = 5; // resource id
int64 creation_unix_timestamp = 6; // unix timestamp in seconds
optional int64 deletion_unix_timestamp = 7; // unix timestamp in seconds
}

message ListCostsResponse {
Expand Down
15 changes: 4 additions & 11 deletions v3/services/costsvc/internal/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ type costGroup struct {
Id string
Kind string
CostGroup string
BasePrice uint64
BasePrice float64
TimeUnit util.TimeUnit
CreationTimestamp int64
DeletionTimestamp *int64
}

func newCostGroup(obj interface{}) (*costGroup, error) {
Expand All @@ -42,22 +41,17 @@ func newCostGroup(obj interface{}) (*costGroup, error) {
if !found {
return nil, fmt.Errorf("%s label not found", labels.CostBasePrice)
}
basePrice, err := strconv.ParseUint(basePriceLabel, 10, 64)
basePrice, err := strconv.ParseFloat(basePriceLabel, 64)
if err != nil {
return nil, fmt.Errorf("%s label value is not an uint", labels.CostBasePrice)
return nil, fmt.Errorf("%s label value is not a float64", labels.CostBasePrice)
}
timeUnitLabel, found := objLabels[labels.CostTimeUnit]
if !found {
return nil, fmt.Errorf("%s label not found", labels.CostTimeUnit)
}
timeUnit, err := util.ParseTimeUnit(timeUnitLabel)
if err != nil {
return nil, err
}

var deletionTimestamp int64
if unstructuredObj.GetDeletionTimestamp() != nil {
deletionTimestamp = unstructuredObj.GetDeletionTimestamp().Unix()
return nil, fmt.Errorf("%s label value is not a valid time unit", labels.CostTimeUnit)
}

return &costGroup{
Expand All @@ -67,7 +61,6 @@ func newCostGroup(obj interface{}) (*costGroup, error) {
BasePrice: basePrice,
TimeUnit: timeUnit,
CreationTimestamp: unstructuredObj.GetCreationTimestamp().Unix(),
DeletionTimestamp: &deletionTimestamp,
}, nil
}

Expand Down
157 changes: 157 additions & 0 deletions v3/services/costsvc/internal/controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package costservice

import (
"github.com/hobbyfarm/gargantua/v3/pkg/labels"
"github.com/hobbyfarm/gargantua/v3/pkg/util"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"testing"
"time"
)

func Test_newCostGroup(t *testing.T) {
creationUnixTimestamp := int64(100)
creation := time.Unix(creationUnixTimestamp, 0)

tests := []struct {
name string
input *unstructured.Unstructured
want *costGroup
wantErr assert.ErrorAssertionFunc
}{
{
name: "ok",
input: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "VirtualMachine",
"metadata": map[string]interface{}{
"name": "vm-test",
"creationTimestamp": creation.Format(time.RFC3339),
"labels": map[string]interface{}{
labels.CostGroup: "my-cost-group",
labels.CostBasePrice: "10.01",
labels.CostTimeUnit: util.TimeUnitSeconds,
},
},
},
},
want: &costGroup{
Id: "vm-test",
Kind: "VirtualMachine",
CostGroup: "my-cost-group",
BasePrice: 10.01,
TimeUnit: util.TimeUnitSeconds,
CreationTimestamp: creationUnixTimestamp,
},
},
{
name: "no cost group",
input: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "VirtualMachine",
"metadata": map[string]interface{}{
"name": "vm-test",
"creationTimestamp": creation.Format(time.RFC3339),
"labels": map[string]interface{}{
labels.CostBasePrice: "10.01",
labels.CostTimeUnit: util.TimeUnitSeconds,
},
},
},
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, labels.CostGroup)
},
},
{
name: "no base price",
input: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "VirtualMachine",
"metadata": map[string]interface{}{
"name": "vm-test",
"creationTimestamp": creation.Format(time.RFC3339),
"labels": map[string]interface{}{
labels.CostGroup: "my-cost-group",
labels.CostTimeUnit: util.TimeUnitSeconds,
},
},
},
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, labels.CostBasePrice)
},
},
{
name: "invalid base price",
input: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "VirtualMachine",
"metadata": map[string]interface{}{
"name": "vm-test",
"creationTimestamp": creation.Format(time.RFC3339),
"labels": map[string]interface{}{
labels.CostGroup: "my-cost-group",
labels.CostBasePrice: "invalid",
labels.CostTimeUnit: util.TimeUnitSeconds,
},
},
},
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, labels.CostBasePrice)
},
},

{
name: "no time unit",
input: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "VirtualMachine",
"metadata": map[string]interface{}{
"name": "vm-test",
"creationTimestamp": creation.Format(time.RFC3339),
"labels": map[string]interface{}{
labels.CostGroup: "my-cost-group",
labels.CostBasePrice: "10.01",
},
},
},
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, labels.CostTimeUnit)
},
},
{
name: "invalid base price",
input: &unstructured.Unstructured{
Object: map[string]interface{}{
"kind": "VirtualMachine",
"metadata": map[string]interface{}{
"name": "vm-test",
"creationTimestamp": creation.Format(time.RFC3339),
"labels": map[string]interface{}{
labels.CostGroup: "my-cost-group",
labels.CostBasePrice: "10.01",
labels.CostTimeUnit: "invalid",
},
},
},
},
wantErr: func(t assert.TestingT, err error, i ...interface{}) bool {
return assert.ErrorContains(t, err, labels.CostTimeUnit)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := newCostGroup(tt.input)
if tt.wantErr != nil {
tt.wantErr(t, err)
} else {
assert.NoErrorf(t, err, "newCostGroup() error = %v", err)
assert.Equal(t, tt.want, got)
}
})
}
}
8 changes: 4 additions & 4 deletions v3/services/costsvc/internal/costservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ import (

type PreparedCost struct {
CostGroup string `json:"cost_group"`
Total uint64 `json:"total"`
Total float64 `json:"total"`
Sources []PreparedCostSource `json:"source"`
}

type PreparedCostSource struct {
Kind string `json:"kind"`
Cost uint64 `json:"cost"`
Count uint64 `json:"count"`
Kind string `json:"kind"`
Cost float64 `json:"cost"`
Count uint64 `json:"count"`
}

func NewPreparedCost(cost *costpb.Cost) PreparedCost {
Expand Down
Loading

0 comments on commit 097d607

Please sign in to comment.