add sets up

This commit is contained in:
mr 2025-06-20 07:51:32 +02:00
parent 938f9f1326
commit d8ccdec501
23 changed files with 277 additions and 92 deletions

View File

@ -15,12 +15,14 @@ import (
"cloud.o-forge.io/core/oc-lib/dbs/mongo"
"cloud.o-forge.io/core/oc-lib/logs"
"cloud.o-forge.io/core/oc-lib/models"
"cloud.o-forge.io/core/oc-lib/models/booking"
"cloud.o-forge.io/core/oc-lib/models/collaborative_area"
"cloud.o-forge.io/core/oc-lib/models/collaborative_area/rules/rule"
"cloud.o-forge.io/core/oc-lib/models/compute_units"
"cloud.o-forge.io/core/oc-lib/models/order"
"cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/models/resources"
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
"cloud.o-forge.io/core/oc-lib/models/utils"
w2 "cloud.o-forge.io/core/oc-lib/models/workflow"
"cloud.o-forge.io/core/oc-lib/models/workflow_execution"
@ -53,6 +55,7 @@ const (
BOOKING = tools.BOOKING
ORDER = tools.ORDER
COMPUTE_UNITS = tools.COMPUTE_UNITS
PURCHASE_RESOURCE = tools.PURCHASE_RESOURCE
)
// will turn into standards api hostnames
@ -585,3 +588,17 @@ func (l *LibData) ToComputeUnits() *compute_units.ComputeUnits {
}
return nil
}
func (l *LibData) ToBookings() *booking.Booking {
if l.Data.GetAccessor(nil).GetType() == tools.BOOKING {
return l.Data.(*booking.Booking)
}
return nil
}
func (l *LibData) ToPurchasedResource() *purchase_resource.PurchaseResource {
if l.Data.GetAccessor(nil).GetType() == tools.COMPUTE_UNITS {
return l.Data.(*purchase_resource.PurchaseResource)
}
return nil
}

25
models/bill/bill.go Normal file
View File

@ -0,0 +1,25 @@
package bill
import (
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
)
/*
* Bill is a struct that represents when emit billing
*/
type Bill struct {
utils.AbstractObject
}
func (r *Bill) StoreDraftDefault() {
r.IsDraft = true
}
func (r *Bill) CanDelete() bool {
return r.IsDraft // only draft ComputeUnits can be deleted
}
func (d *Bill) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor(request) // Create a new instance of the accessor
}

View File

@ -0,0 +1,63 @@
package bill
import (
"cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/logs"
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
)
type billMongoAccessor struct {
utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller)
}
// New creates a new instance of the billMongoAccessor
func NewAccessor(request *tools.APIRequest) *billMongoAccessor {
return &billMongoAccessor{
AbstractAccessor: utils.AbstractAccessor{
Logger: logs.CreateLogger(tools.COMPUTE_UNITS.String()), // Create a logger with the data type
Request: request,
Type: tools.COMPUTE_UNITS,
},
}
}
/*
* Nothing special here, just the basic CRUD operations
*/
func (a *billMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) {
return utils.GenericDeleteOne(id, a)
}
func (a *billMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) {
// should verify if a source is existing...
return utils.GenericUpdateOne(set, id, a, &Bill{})
}
func (a *billMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) {
return utils.GenericStoreOne(data.(*Bill), a)
}
func (a *billMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) {
return utils.GenericStoreOne(data.(*Bill), a)
}
func (a *billMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) {
return utils.GenericLoadOne[*Bill](id, func(d utils.DBObject) (utils.DBObject, int, error) {
return d, 200, nil
}, a)
}
func (a *billMongoAccessor) LoadAll(isDraft bool) ([]utils.ShallowDBObject, int, error) {
return utils.GenericLoadAll[*Bill](a.getExec(), isDraft, a)
}
func (a *billMongoAccessor) Search(filters *dbs.Filters, search string, isDraft bool) ([]utils.ShallowDBObject, int, error) {
return utils.GenericSearch[*Bill](filters, search, (&Bill{}).GetObjectFilters(search), a.getExec(), isDraft, a)
}
func (a *billMongoAccessor) getExec() func(utils.DBObject) utils.ShallowDBObject {
return func(d utils.DBObject) utils.ShallowDBObject {
return d
}
}

View File

@ -9,7 +9,8 @@ import (
type PricedItemITF interface {
GetID() string
GetType() tools.DataType
IsPurchased() bool
IsPurchasable() bool
IsBooked() bool
GetCreatorID() string
GetLocationStart() *time.Time
SetLocationStart(start time.Time)

View File

@ -6,7 +6,8 @@ import (
type PricingProfileITF interface {
GetPrice(quantity float64, val float64, start time.Time, end time.Time, params ...string) (float64, error)
IsPurchased() bool
IsPurchasable() bool
IsBooked() bool
GetOverrideStrategyValue() int
}

View File

@ -7,21 +7,65 @@ import (
"time"
)
type BillingStrategy int // BAM BAM
// should except... on
const (
BILL_ONCE BillingStrategy = iota // is a permanent buying ( predictible )
BILL_PER_WEEK
BILL_PER_MONTH
BILL_PER_YEAR
)
func (t BillingStrategy) IsBillingStrategyAllowed(bs int) (BillingStrategy, bool) {
switch t {
case BILL_ONCE:
return BILL_ONCE, bs == 0
case BILL_PER_WEEK:
case BILL_PER_MONTH:
case BILL_PER_YEAR:
return t, bs != 0
}
return t, false
}
func (t BillingStrategy) String() string {
return [...]string{"BILL_ONCE", "BILL_PER_WEEK", "BILL_PER_MONTH", "BILL_PER_YEAR"}[t]
}
func BillingStrategyList() []BillingStrategy {
return []BillingStrategy{BILL_ONCE, BILL_PER_WEEK, BILL_PER_MONTH, BILL_PER_YEAR}
}
type BuyingStrategy int
// should except... on
const (
UNLIMITED BuyingStrategy = iota
SUBSCRIPTION
PAY_PER_USE
PERMANENT BuyingStrategy = iota // is a permanent buying ( predictible )
UNDEFINED_SUBSCRIPTION // a endless subscription ( unpredictible )
SUBSCRIPTION // a defined subscription ( predictible )
// PAY_PER_USE // per request. ( unpredictible )
)
func (t BuyingStrategy) String() string {
return [...]string{"UNLIMITED", "SUBSCRIPTION", "PAY PER USE"}[t]
return [...]string{"PERMANENT", "UNDEFINED_SUBSCRIPTION", "SUBSCRIPTION"}[t]
}
func (t BuyingStrategy) IsBillingStrategyAllowed(bs BillingStrategy) (BillingStrategy, bool) {
switch t {
case PERMANENT:
return BILL_ONCE, bs == BILL_ONCE
case UNDEFINED_SUBSCRIPTION:
return BILL_PER_MONTH, bs != BILL_ONCE
case SUBSCRIPTION:
/*case PAY_PER_USE:
return bs, true*/
}
return bs, false
}
func BuyingStrategyList() []BuyingStrategy {
return []BuyingStrategy{UNLIMITED, SUBSCRIPTION, PAY_PER_USE}
return []BuyingStrategy{PERMANENT, UNDEFINED_SUBSCRIPTION, SUBSCRIPTION}
}
type Strategy interface {
@ -118,7 +162,7 @@ type PricingStrategy[T Strategy] struct {
func (p PricingStrategy[T]) GetPrice(amountOfData float64, bookingTimeDuration float64, start time.Time, end *time.Time) (float64, error) {
if p.BuyingStrategy == SUBSCRIPTION {
return BookingEstimation(p.GetTimePricingStrategy(), p.Price*float64(amountOfData), bookingTimeDuration, start, end)
} else if p.BuyingStrategy == UNLIMITED {
} else if p.BuyingStrategy == PERMANENT {
return p.Price, nil
}
return p.Price * float64(amountOfData), nil

View File

@ -15,9 +15,9 @@ func (d DummyStrategy) GetStrategy() string { return "DUMMY" }
func (d DummyStrategy) GetStrategyValue() int { return int(d) }
func TestBuyingStrategy_String(t *testing.T) {
assert.Equal(t, "UNLIMITED", pricing.UNLIMITED.String())
assert.Equal(t, "UNLIMITED", pricing.PERMANENT.String())
assert.Equal(t, "SUBSCRIPTION", pricing.SUBSCRIPTION.String())
assert.Equal(t, "PAY PER USE", pricing.PAY_PER_USE.String())
//assert.Equal(t, "PAY PER USE", pricing.PAY_PER_USE.String())
}
func TestBuyingStrategyList(t *testing.T) {
@ -116,13 +116,13 @@ func TestPricingStrategy_GetPrice(t *testing.T) {
assert.True(t, p > 0)
// UNLIMITED case
ps.BuyingStrategy = pricing.UNLIMITED
ps.BuyingStrategy = pricing.PERMANENT
p, err = ps.GetPrice(10, 0, start, &end)
assert.NoError(t, err)
assert.Equal(t, 5.0, p)
// PAY_PER_USE case
ps.BuyingStrategy = pricing.PAY_PER_USE
//ps.BuyingStrategy = pricing.PAY_PER_USE
p, err = ps.GetPrice(3, 0, start, &end)
assert.NoError(t, err)
assert.Equal(t, 15.0, p)

View File

@ -2,6 +2,7 @@ package models
import (
"cloud.o-forge.io/core/oc-lib/logs"
"cloud.o-forge.io/core/oc-lib/models/bill"
"cloud.o-forge.io/core/oc-lib/models/compute_units"
"cloud.o-forge.io/core/oc-lib/models/order"
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
@ -40,6 +41,7 @@ var ModelsCatalog = map[string]func() utils.DBObject{
tools.ORDER.String(): func() utils.DBObject { return &order.Order{} },
tools.PURCHASE_RESOURCE.String(): func() utils.DBObject { return &purchase_resource.PurchaseResource{} },
tools.COMPUTE_UNITS.String(): func() utils.DBObject { return &compute_units.ComputeUnits{} },
tools.BILL.String(): func() utils.DBObject { return &bill.Bill{} },
}
// Model returns the model object based on the model type

View File

@ -265,7 +265,7 @@ func (d *PeerOrder) Pay(request *tools.APIRequest, response chan *PeerOrder, wg
d.Status = enum.PAID // TO REMOVE LATER IT'S A MOCK
if d.Status == enum.PAID {
for _, b := range d.Items {
if !b.Item.IsPurchased() {
if !b.Item.IsPurchasable() {
continue
}
accessor := purchase_resource.NewAccessor(request)

View File

@ -80,8 +80,15 @@ type ComputeResourcePricingProfile struct {
RAMPrice float64 `json:"ram_price" bson:"ram_price" default:"-1"` // RAMPrice is the price of the RAM
}
func (p *ComputeResourcePricingProfile) IsPurchased() bool {
return p.Pricing.BuyingStrategy != pricing.PAY_PER_USE
func (p *ComputeResourcePricingProfile) IsPurchasable() bool {
return p.Pricing.BuyingStrategy != pricing.UNDEFINED_SUBSCRIPTION
}
func (p *ComputeResourcePricingProfile) IsBooked() bool {
if p.Pricing.BuyingStrategy == pricing.PERMANENT {
p.Pricing.BuyingStrategy = pricing.SUBSCRIPTION
}
return true
}
func (p *ComputeResourcePricingProfile) GetOverrideStrategyValue() int {

View File

@ -137,8 +137,13 @@ func (p *DataResourcePricingProfile) GetPrice(amountOfData float64, explicitDura
return p.Pricing.GetPrice(amountOfData, explicitDuration, start, &end)
}
func (p *DataResourcePricingProfile) IsPurchased() bool {
return p.Pricing.BuyingStrategy != pricing.PAY_PER_USE
func (p *DataResourcePricingProfile) IsPurchasable() bool {
return p.Pricing.BuyingStrategy != pricing.UNDEFINED_SUBSCRIPTION
}
func (p *DataResourcePricingProfile) IsBooked() bool {
// TODO WHAT ABOUT PAY PER USE... it's a complicate CASE
return p.Pricing.BuyingStrategy != pricing.PERMANENT
}
type PricedDataResource struct {

View File

@ -35,11 +35,18 @@ func (abs *PricedResource) GetCreatorID() string {
return abs.CreatorID
}
func (abs *PricedResource) IsPurchased() bool {
func (abs *PricedResource) IsPurchasable() bool {
if abs.SelectedPricing == nil {
return false
}
return (abs.SelectedPricing).IsPurchased()
return (abs.SelectedPricing).IsPurchasable()
}
func (abs *PricedResource) IsBooked() bool {
if abs.SelectedPricing == nil {
return false
}
return (abs.SelectedPricing).IsBooked()
}
func (abs *PricedResource) GetLocationEnd() *time.Time {

View File

@ -77,8 +77,12 @@ type ProcessingResourcePricingProfile struct {
pricing.AccessPricingProfile[pricing.TimePricingStrategy] // AccessPricingProfile is the pricing profile of a data it means that we can access the data for an amount of time
}
func (p *ProcessingResourcePricingProfile) IsPurchased() bool {
return p.Pricing.BuyingStrategy != pricing.PAY_PER_USE
func (p *ProcessingResourcePricingProfile) IsPurchasable() bool {
return p.Pricing.BuyingStrategy != pricing.UNDEFINED_SUBSCRIPTION
}
func (p *ProcessingResourcePricingProfile) IsBooked() bool {
return p.Pricing.BuyingStrategy != pricing.PERMANENT
}
func (p *ProcessingResourcePricingProfile) GetPrice(amountOfData float64, val float64, start time.Time, end time.Time, params ...string) (float64, error) {

View File

@ -52,7 +52,8 @@ type AbstractInstanciatedResource[T ResourceInstanceITF] struct {
Instances []T `json:"instances,omitempty" bson:"instances,omitempty"` // Bill is the bill of the resource // Bill is the bill of the resource
}
func (abs *AbstractInstanciatedResource[T]) ConvertToPricedResource(t tools.DataType, request *tools.APIRequest, buyingStrategy int, pricingStrategy int) pricing.PricedItemITF {
func (abs *AbstractInstanciatedResource[T]) ConvertToPricedResource(
t tools.DataType, request *tools.APIRequest, buyingStrategy int, pricingStrategy int) pricing.PricedItemITF {
instances := map[string]string{}
profiles := []pricing.PricingProfileITF{}
for _, instance := range abs.Instances {

View File

@ -152,8 +152,15 @@ type StorageResourcePricingProfile struct {
pricing.ExploitPricingProfile[StorageResourcePricingStrategy] // ExploitPricingProfile is the pricing profile of a storage it means that we exploit the resource for an amount of continuous time
}
func (p *StorageResourcePricingProfile) IsPurchased() bool {
return p.Pricing.BuyingStrategy != pricing.PAY_PER_USE
func (p *StorageResourcePricingProfile) IsPurchasable() bool {
return p.Pricing.BuyingStrategy != pricing.UNDEFINED_SUBSCRIPTION
}
func (p *StorageResourcePricingProfile) IsBooked() bool {
if p.Pricing.BuyingStrategy == pricing.PERMANENT {
p.Pricing.BuyingStrategy = pricing.SUBSCRIPTION
}
return true
}
func (p *StorageResourcePricingProfile) GetPrice(amountOfData float64, val float64, start time.Time, end time.Time, params ...string) (float64, error) {

View File

@ -76,11 +76,8 @@ func TestDataResourcePricingStrategy_GetQuantity(t *testing.T) {
func TestDataResourcePricingProfile_IsPurchased(t *testing.T) {
profile := &resources.DataResourcePricingProfile{}
profile.Pricing.BuyingStrategy = pricing.PAY_PER_USE
assert.False(t, profile.IsPurchased())
profile.Pricing.BuyingStrategy = pricing.SUBSCRIPTION
assert.True(t, profile.IsPurchased())
assert.True(t, profile.IsPurchasable())
}
func TestPricedDataResource_GetPrice(t *testing.T) {

View File

@ -22,7 +22,7 @@ type MockPricingProfile struct {
ReturnCost float64
}
func (m *MockPricingProfile) IsPurchased() bool {
func (m *MockPricingProfile) IsPurchasable() bool {
return m.Purchased
}
@ -49,13 +49,13 @@ func TestGetIDAndCreatorAndType(t *testing.T) {
func TestIsPurchased(t *testing.T) {
t.Run("nil selected pricing returns false", func(t *testing.T) {
r := &resources.PricedResource{}
assert.False(t, r.IsPurchased())
assert.False(t, r.IsPurchasable())
})
t.Run("returns true if pricing profile is purchased", func(t *testing.T) {
mock := &MockPricingProfile{Purchased: true}
r := &resources.PricedResource{SelectedPricing: mock}
assert.True(t, r.IsPurchased())
assert.True(t, r.IsPurchasable())
})
}

View File

@ -95,21 +95,12 @@ func TestProcessingResourcePricingProfile_GetPrice(t *testing.T) {
}
func TestProcessingResourcePricingProfile_IsPurchased(t *testing.T) {
nonPurchased := &ProcessingResourcePricingProfile{
AccessPricingProfile: pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
BuyingStrategy: pricing.PAY_PER_USE,
},
},
}
assert.False(t, nonPurchased.IsPurchased())
purchased := &ProcessingResourcePricingProfile{
AccessPricingProfile: pricing.AccessPricingProfile[pricing.TimePricingStrategy]{
Pricing: pricing.PricingStrategy[pricing.TimePricingStrategy]{
BuyingStrategy: pricing.UNLIMITED,
BuyingStrategy: pricing.PERMANENT,
},
},
}
assert.True(t, purchased.IsPurchased())
assert.True(t, purchased.IsPurchasable())
}

View File

@ -2,10 +2,8 @@ package resources_test
import (
"testing"
"time"
"cloud.o-forge.io/core/oc-lib/models/common/models"
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/tools"
"github.com/stretchr/testify/assert"
@ -107,43 +105,3 @@ func TestPricedStorageResource_GetPrice_NoProfiles(t *testing.T) {
_, err := res.GetPrice()
assert.Error(t, err)
}
func TestPricedStorageResource_GetPrice_WithPricing(t *testing.T) {
now := time.Now()
end := now.Add(2 * time.Hour)
profile := &resources.StorageResourcePricingProfile{
ExploitPricingProfile: pricing.ExploitPricingProfile[resources.StorageResourcePricingStrategy]{
AccessPricingProfile: pricing.AccessPricingProfile[resources.StorageResourcePricingStrategy]{
Pricing: pricing.PricingStrategy[resources.StorageResourcePricingStrategy]{
BuyingStrategy: pricing.PAY_PER_USE,
Price: 42.0,
},
},
},
}
res := &resources.PricedStorageResource{
PricedResource: resources.PricedResource{
UsageStart: &now,
UsageEnd: &end,
PricingProfiles: []pricing.PricingProfileITF{profile},
},
UsageStorageGB: 1.0,
}
price, err := res.GetPrice()
assert.NoError(t, err)
assert.Equal(t, 42.0, price)
}
func TestStorageResourcePricingProfile_IsPurchased(t *testing.T) {
p := &resources.StorageResourcePricingProfile{
ExploitPricingProfile: pricing.ExploitPricingProfile[resources.StorageResourcePricingStrategy]{
AccessPricingProfile: pricing.AccessPricingProfile[resources.StorageResourcePricingStrategy]{
Pricing: pricing.PricingStrategy[resources.StorageResourcePricingStrategy]{BuyingStrategy: pricing.PAY_PER_USE},
},
},
}
assert.False(t, p.IsPurchased())
p.Pricing.BuyingStrategy = pricing.UNLIMITED
assert.True(t, p.IsPurchased())
}

View File

@ -169,8 +169,8 @@ func (wfa *Workflow) CheckBooking(caller *tools.HTTPCaller) (bool, error) {
func (wf *Workflow) Planify(start time.Time, end *time.Time, request *tools.APIRequest, buyingStrategy int, pricingStrategy int) (float64, map[tools.DataType]map[string]pricing.PricedItemITF, *Workflow, error) {
priceds := map[tools.DataType]map[string]pricing.PricedItemITF{}
ps, priceds, err := plan[*resources.ProcessingResource](tools.PROCESSING_RESOURCE, wf, priceds, request,
buyingStrategy, pricingStrategy,
wf.Graph.IsProcessing, func(res resources.ResourceInterface, priced pricing.PricedItemITF) (time.Time, float64) {
buyingStrategy, pricingStrategy, wf.Graph.IsProcessing,
func(res resources.ResourceInterface, priced pricing.PricedItemITF) (time.Time, float64) {
return start.Add(time.Duration(wf.Graph.GetAverageTimeProcessingBeforeStart(0, res.GetID(), request, buyingStrategy, pricingStrategy)) * time.Second), priced.GetExplicitDurationInS()
}, func(started time.Time, duration float64) *time.Time {
s := started.Add(time.Duration(duration))

View File

@ -8,6 +8,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/booking"
"cloud.o-forge.io/core/oc-lib/models/common/enum"
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
"github.com/google/uuid"
@ -21,6 +22,7 @@ import (
*/
type WorkflowExecution struct {
utils.AbstractObject // AbstractObject contains the basic fields of an object (id, name)
PeerBuyByGraph map[string]map[string][]string `json:"peer_buy_by_graph,omitempty" bson:"peer_buy_by_graph,omitempty"` // BookByResource is a map of the resource id and the list of the booking id
PeerBookByGraph map[string]map[string][]string `json:"peer_book_by_graph,omitempty" bson:"peer_book_by_graph,omitempty"` // BookByResource is a map of the resource id and the list of the booking id
ExecutionsID string `json:"executions_id,omitempty" bson:"executions_id,omitempty"`
ExecDate time.Time `json:"execution_date,omitempty" bson:"execution_date,omitempty" validate:"required"` // ExecDate is the execution date of the workflow, is required
@ -110,10 +112,51 @@ func (d *WorkflowExecution) VerifyAuth(request *tools.APIRequest) bool {
}
/*
booking is an activity reserved for not a long time investment.
... purchase is dependant of a one time buying.
use of a datacenter or storage can't be buy for permanent.
booking is an activity reserved for not a long time investment.
... purchase is dependant of a one time buying.
use of a datacenter or storage can't be buy for permanent access.
*/
func (d *WorkflowExecution) Buy(bs pricing.BillingStrategy, executionsID string, wfID string, priceds map[tools.DataType]map[string]pricing.PricedItemITF) []*purchase_resource.PurchaseResource {
purchases := d.buyEach(bs, executionsID, wfID, tools.PROCESSING_RESOURCE, priceds[tools.PROCESSING_RESOURCE])
purchases = append(purchases, d.buyEach(bs, executionsID, wfID, tools.DATA_RESOURCE, priceds[tools.DATA_RESOURCE])...)
return purchases
}
func (d *WorkflowExecution) buyEach(bs pricing.BillingStrategy, executionsID string, wfID string, dt tools.DataType, priceds map[string]pricing.PricedItemITF) []*purchase_resource.PurchaseResource {
items := []*purchase_resource.PurchaseResource{}
for itemID, priced := range priceds {
if !priced.IsPurchasable() && bs == pricing.BILL_ONCE { // buy only that must be buy
continue
}
if d.PeerBuyByGraph == nil {
d.PeerBuyByGraph = map[string]map[string][]string{}
}
if d.PeerBuyByGraph[priced.GetCreatorID()] == nil {
d.PeerBuyByGraph[priced.GetCreatorID()] = map[string][]string{}
}
if d.PeerBuyByGraph[priced.GetCreatorID()][itemID] == nil {
d.PeerBuyByGraph[priced.GetCreatorID()][itemID] = []string{}
}
start := d.ExecDate
if s := priced.GetLocationStart(); s != nil {
start = *s
}
end := start.Add(time.Duration(priced.GetExplicitDurationInS()) * time.Second)
bookingItem := &purchase_resource.PurchaseResource{
AbstractObject: utils.AbstractObject{
UUID: uuid.New().String(),
Name: d.GetName() + "_" + executionsID + "_" + wfID,
},
ResourceID: priced.GetID(),
ResourceType: dt,
EndDate: &end,
}
items = append(items, bookingItem)
d.PeerBuyByGraph[priced.GetCreatorID()][itemID] = append(
d.PeerBuyByGraph[priced.GetCreatorID()][itemID], bookingItem.GetID())
}
return items
}
func (d *WorkflowExecution) Book(executionsID string, wfID string, priceds map[tools.DataType]map[string]pricing.PricedItemITF) []*booking.Booking {
booking := d.bookEach(executionsID, wfID, tools.STORAGE_RESOURCE, priceds[tools.STORAGE_RESOURCE])
@ -126,6 +169,9 @@ func (d *WorkflowExecution) Book(executionsID string, wfID string, priceds map[t
func (d *WorkflowExecution) bookEach(executionsID string, wfID string, dt tools.DataType, priceds map[string]pricing.PricedItemITF) []*booking.Booking {
items := []*booking.Booking{}
for itemID, priced := range priceds {
if !priced.IsBooked() { // book only that must be booked
continue
}
if d.PeerBookByGraph == nil {
d.PeerBookByGraph = map[string]map[string][]string{}
}

View File

@ -11,6 +11,7 @@ import (
"cloud.o-forge.io/core/oc-lib/models/common/enum"
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/models/peer"
"cloud.o-forge.io/core/oc-lib/models/resources/purchase_resource"
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/models/workflow"
"cloud.o-forge.io/core/oc-lib/tools"
@ -34,8 +35,9 @@ type WorkflowSchedule struct {
DurationS float64 `json:"duration_s" default:"-1"` // End is the end time of the schedule
Cron string `json:"cron,omitempty"` // here the cron format : ss mm hh dd MM dw task
SelectedBuyingStrategy pricing.BuyingStrategy `json:"selected_buying_strategy"`
SelectedPricingStrategy int `json:"selected_pricing_strategy"`
SelectedBuyingStrategy pricing.BuyingStrategy `json:"selected_buying_strategy"`
SelectedPricingStrategy int `json:"selected_pricing_strategy"`
SelectedBillingStrategy pricing.BillingStrategy `json:"selected_billing_strategy"`
}
func NewScheduler(start string, end string, durationInS float64, cron string) *WorkflowSchedule {
@ -79,8 +81,10 @@ func (ws *WorkflowSchedule) CheckBooking(wfID string, request *tools.APIRequest)
if err != nil {
return false, wf, []*WorkflowExecution{}, []*booking.Booking{}, err
}
purchased := []*purchase_resource.PurchaseResource{}
bookings := []*booking.Booking{}
for _, exec := range execs {
purchased = append(purchased, exec.Buy(ws.SelectedBillingStrategy, ws.UUID, wfID, priceds)...)
bookings = append(bookings, exec.Book(ws.UUID, wfID, priceds)...)
}

View File

@ -27,6 +27,7 @@ const (
ADMIRALTY_KUBECONFIG
ADMIRALTY_NODES
COMPUTE_UNITS
BILL
)
var NOAPI = ""
@ -67,6 +68,7 @@ var DefaultAPI = [...]string{
ADMIRALTY_KUBECONFIGAPI,
ADMIRALTY_NODESAPI,
DATACENTERAPI,
NOAPI,
}
// Bind the standard data name to the data type
@ -94,6 +96,7 @@ var Str = [...]string{
"admiralty_kubeconfig",
"admiralty_node",
"compute_units",
"bill",
}
func FromInt(i int) string {
@ -114,5 +117,7 @@ func (d DataType) EnumIndex() int {
}
func DataTypeList() []DataType {
return []DataType{DATA_RESOURCE, PROCESSING_RESOURCE, STORAGE_RESOURCE, COMPUTE_RESOURCE, WORKFLOW_RESOURCE, WORKFLOW, WORKFLOW_EXECUTION, WORKSPACE, PEER, COLLABORATIVE_AREA, RULE, BOOKING, WORKFLOW_HISTORY, WORKSPACE_HISTORY, ORDER, PURCHASE_RESOURCE, ADMIRALTY_SOURCE, ADMIRALTY_TARGET, ADMIRALTY_SECRET, ADMIRALTY_KUBECONFIG, ADMIRALTY_NODES}
return []DataType{DATA_RESOURCE, PROCESSING_RESOURCE, STORAGE_RESOURCE, COMPUTE_RESOURCE, WORKFLOW_RESOURCE,
WORKFLOW, WORKFLOW_EXECUTION, WORKSPACE, PEER, COLLABORATIVE_AREA, RULE, BOOKING, WORKFLOW_HISTORY, WORKSPACE_HISTORY,
ORDER, PURCHASE_RESOURCE, ADMIRALTY_SOURCE, ADMIRALTY_TARGET, ADMIRALTY_SECRET, ADMIRALTY_KUBECONFIG, ADMIRALTY_NODES, COMPUTE_UNITS, BILL}
}