From 2264d22c691da72ab9bb9261cb9765273be13d0f Mon Sep 17 00:00:00 2001 From: mr Date: Tue, 17 Jun 2025 14:21:37 +0200 Subject: [PATCH] draft of compute units catalog --- entrypoint.go | 1 + models/compute_units/compute_units.go | 44 +++++++++ .../compute_units_mongo_accessor.go | 94 +++++++++++++++++++ models/models.go | 2 + .../tests/purchase_resource_test.go | 2 +- tools/enums.go | 15 +-- 6 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 models/compute_units/compute_units.go create mode 100644 models/compute_units/compute_units_mongo_accessor.go diff --git a/entrypoint.go b/entrypoint.go index db4cf08..8339b41 100644 --- a/entrypoint.go +++ b/entrypoint.go @@ -51,6 +51,7 @@ const ( RULE = tools.RULE BOOKING = tools.BOOKING ORDER = tools.ORDER + COMPUTE_UNITS = tools.COMPUTE_UNITS ) // will turn into standards api hostnames diff --git a/models/compute_units/compute_units.go b/models/compute_units/compute_units.go new file mode 100644 index 0000000..5fca0c1 --- /dev/null +++ b/models/compute_units/compute_units.go @@ -0,0 +1,44 @@ +package compute_units + +import ( + "cloud.o-forge.io/core/oc-lib/models/common/enum" + "cloud.o-forge.io/core/oc-lib/models/common/models" + "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/tools" + "github.com/biter777/countries" +) + +/* +* ComputeUnits is a struct that represents a compute units in your datacenters + */ + +type ComputeUnits struct { + utils.AbstractObject + MonitorPath string `json:"monitor_path,omitempty" bson:"monitor_path,omitempty"` + Location resources.GeoPoint `json:"location,omitempty" bson:"location,omitempty"` + Country countries.CountryCode `json:"country,omitempty" bson:"country,omitempty"` + AccessProtocol string `json:"access_protocol,omitempty" bson:"access_protocol,omitempty"` + Architecture string `json:"architecture,omitempty" bson:"architecture,omitempty"` // Architecture is the architecture + Infrastructure enum.InfrastructureType `json:"infrastructure" bson:"infrastructure" default:"-1"` // Infrastructure is the infrastructure + Source string `json:"source,omitempty" bson:"source,omitempty"` // Source is the source of the resource + SecurityLevel string `json:"security_level,omitempty" bson:"security_level,omitempty"` + PowerSources []string `json:"power_sources,omitempty" bson:"power_sources,omitempty"` + AnnualCO2Emissions float64 `json:"annual_co2_emissions,omitempty" bson:"co2_emissions,omitempty"` + CPUs map[string]*models.CPU `bson:"cpus,omitempty" json:"cpus,omitempty"` // CPUs is the list of CPUs key is model + GPUs map[string]*models.GPU `bson:"gpus,omitempty" json:"gpus,omitempty"` // GPUs is the list of GPUs key is model + Nodes []*resources.ComputeNode `json:"nodes,omitempty" bson:"nodes,omitempty"` + ResourceID string `json:"-" bson:"-"` +} + +func (r *ComputeUnits) StoreDraftDefault() { + r.IsDraft = true +} + +func (r *ComputeUnits) CanDelete() bool { + return r.IsDraft // only draft ComputeUnits can be deleted +} + +func (d *ComputeUnits) GetAccessor(request *tools.APIRequest) utils.Accessor { + return NewAccessor(request) // Create a new instance of the accessor +} diff --git a/models/compute_units/compute_units_mongo_accessor.go b/models/compute_units/compute_units_mongo_accessor.go new file mode 100644 index 0000000..0922c10 --- /dev/null +++ b/models/compute_units/compute_units_mongo_accessor.go @@ -0,0 +1,94 @@ +package compute_units + +import ( + "encoding/json" + "errors" + + "cloud.o-forge.io/core/oc-lib/dbs" + "cloud.o-forge.io/core/oc-lib/logs" + "cloud.o-forge.io/core/oc-lib/models/resources" + "cloud.o-forge.io/core/oc-lib/models/utils" + "cloud.o-forge.io/core/oc-lib/tools" +) + +type computeUnitsMongoAccessor struct { + utils.AbstractAccessor // AbstractAccessor contains the basic fields of an accessor (model, caller) +} + +// New creates a new instance of the computeUnitsMongoAccessor +func NewAccessor(request *tools.APIRequest) *computeUnitsMongoAccessor { + return &computeUnitsMongoAccessor{ + 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 *computeUnitsMongoAccessor) DeleteOne(id string) (utils.DBObject, int, error) { + return utils.GenericDeleteOne(id, a) +} + +func (a *computeUnitsMongoAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) { + return utils.GenericUpdateOne(set, id, a, &ComputeUnits{}) +} + +func (a *computeUnitsMongoAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) { + return utils.GenericStoreOne(data.(*ComputeUnits), a) +} + +func (a *computeUnitsMongoAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) { + // is a publisher... that become a resources. + if data.IsDrafted() { + return nil, 422, errors.New("can't publish a drafted compute units") + } + computeUnits := data.(*ComputeUnits) + resAccess := resources.NewAccessor[*resources.ComputeResource](tools.COMPUTE_RESOURCE, a.Request, func() utils.DBObject { return &resources.ComputeResource{} }) + var instance *resources.ComputeResourceInstance + b, _ := json.Marshal(computeUnits) + json.Unmarshal(b, instance) + + if computeUnits.ResourceID != "" { + // TODO dependent of a existing resource + res, code, err := resAccess.LoadOne(computeUnits.ResourceID) + if err == nil { + return nil, code, err + } + existingComputeResource := res.(*resources.ComputeResource) + if existingComputeResource.Architecture != computeUnits.Architecture || existingComputeResource.Infrastructure != computeUnits.Infrastructure { + return nil, 422, errors.New("should be same architecture & infrastructure from the resource") + } + existingComputeResource.Instances = append(existingComputeResource.Instances, instance) + return resAccess.UpdateOne(existingComputeResource, existingComputeResource.UUID) + } else { + var resource *resources.ComputeResource + b, _ := json.Marshal(computeUnits) + json.Unmarshal(b, resource) + resource.Instances = append(resource.Instances, instance) + return resAccess.StoreOne(resource) + } +} + +func (a *computeUnitsMongoAccessor) LoadOne(id string) (utils.DBObject, int, error) { + return utils.GenericLoadOne[*ComputeUnits](id, func(d utils.DBObject) (utils.DBObject, int, error) { + return d, 200, nil + }, a) +} + +func (a *computeUnitsMongoAccessor) LoadAll(isDraft bool) ([]utils.ShallowDBObject, int, error) { + return utils.GenericLoadAll[*ComputeUnits](a.getExec(), isDraft, a) +} + +func (a *computeUnitsMongoAccessor) Search(filters *dbs.Filters, search string, isDraft bool) ([]utils.ShallowDBObject, int, error) { + return utils.GenericSearch[*ComputeUnits](filters, search, (&ComputeUnits{}).GetObjectFilters(search), a.getExec(), isDraft, a) +} + +func (a *computeUnitsMongoAccessor) getExec() func(utils.DBObject) utils.ShallowDBObject { + return func(d utils.DBObject) utils.ShallowDBObject { + return d + } +} diff --git a/models/models.go b/models/models.go index 986ce41..41fdffb 100644 --- a/models/models.go +++ b/models/models.go @@ -2,6 +2,7 @@ package models import ( "cloud.o-forge.io/core/oc-lib/logs" + "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" "cloud.o-forge.io/core/oc-lib/tools" @@ -38,6 +39,7 @@ var ModelsCatalog = map[string]func() utils.DBObject{ tools.WORKSPACE_HISTORY.String(): func() utils.DBObject { return &w3.WorkspaceHistory{} }, 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{} }, } // Model returns the model object based on the model type diff --git a/models/resources/purchase_resource/tests/purchase_resource_test.go b/models/resources/purchase_resource/tests/purchase_resource_test.go index ec6abae..99b7184 100644 --- a/models/resources/purchase_resource/tests/purchase_resource_test.go +++ b/models/resources/purchase_resource/tests/purchase_resource_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "cloud.o-forge.io/core/oc-lib/models/purchase_resource" + "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" ) diff --git a/tools/enums.go b/tools/enums.go index 106c22f..2bb54e0 100644 --- a/tools/enums.go +++ b/tools/enums.go @@ -26,6 +26,7 @@ const ( ADMIRALTY_SECRET ADMIRALTY_KUBECONFIG ADMIRALTY_NODES + COMPUTE_UNITS ) var NOAPI = "" @@ -35,11 +36,11 @@ var WORKFLOWAPI = "oc-workflow" var WORKSPACEAPI = "oc-workspace" var PEERSAPI = "oc-peer" var DATACENTERAPI = "oc-datacenter" -var ADMIRALTY_SOURCEAPI = DATACENTERAPI+"/admiralty/source" -var ADMIRALTY_TARGETAPI = DATACENTERAPI+"/admiralty/target" -var ADMIRALTY_SECRETAPI = DATACENTERAPI+"/admiralty/secret" -var ADMIRALTY_KUBECONFIGAPI = DATACENTERAPI+"/admiralty/kubeconfig" -var ADMIRALTY_NODESAPI = DATACENTERAPI+"/admiralty/node" +var ADMIRALTY_SOURCEAPI = DATACENTERAPI + "/admiralty/source" +var ADMIRALTY_TARGETAPI = DATACENTERAPI + "/admiralty/target" +var ADMIRALTY_SECRETAPI = DATACENTERAPI + "/admiralty/secret" +var ADMIRALTY_KUBECONFIGAPI = DATACENTERAPI + "/admiralty/kubeconfig" +var ADMIRALTY_NODESAPI = DATACENTERAPI + "/admiralty/node" // Bind the standard API name to the data type var DefaultAPI = [...]string{ @@ -65,6 +66,7 @@ var DefaultAPI = [...]string{ ADMIRALTY_SECRETAPI, ADMIRALTY_KUBECONFIGAPI, ADMIRALTY_NODESAPI, + DATACENTERAPI, } // Bind the standard data name to the data type @@ -91,6 +93,7 @@ var Str = [...]string{ "admiralty_secret", "admiralty_kubeconfig", "admiralty_node", + "compute_units", } func FromInt(i int) string { @@ -111,5 +114,5 @@ 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} }