main v1.8.1
nlloskutova 9 months ago
parent e7c968797b
commit 3393934456

@ -1,197 +1,32 @@
## Version 1.8.0
## Version 1.8.1
### Feature
#### account:
- Add endpoints GrantAccessTemplates, ListAvailableTemplates, RevokeAccessTemplates in cloudbroker/account
- Add SortBy field for list groups and validation functionality
- Add ComputeFeatures field to RecordAccount and ItemAccount models in cloudapi/account
- Add ComputeFeatures field to InfoAccount and CreateRequest model in cloudbroker/account
- Add UpdateComputeFeatures endpoint in cloudbroker/account
- Add ExtnetId, FreeIPs fields to model ItemVINS in cloudapi/account and cloudbroker/account
#### audit:
- Add field GUID in model ItemLinkedJobs cloudbroker/audit
- Delete field StatusCode in model ListRequest cloudbroker/audit
- Add fields MinStatusCode and MaxStatusCode in model ListRequest cloudbroker/audit
#### bservice:
- Add validation of RAM to be divisible by 128 in cloudapi/bservice
#### compute:
- Add field CdImageId in models ItemCompute and RecordCompute in cloudapi/compute and cloudbroker/compute
- Add fields NatableVINSID, NatableVINSIP, NatableVINSName, NatableVINSNetwork, NatableVINSNetworkName in models RecordCompute in cloudbroker/compute
- Set field LocalBasePort in model PFWAddRequest as optional in cloudapi/compute and cloudbroker/compute
- Add SortBy field for list groups and validation functionality
- Add HPBacked, CPUPin, NumaAffinity fields to RecordCompute and InfoCompute models in cloudbroker/compute
- Add HPBacked, CPUPin, NumaAffinity fields to RecordCompute and ItemCompute models in cloudapi/compute
- Add validation of RAM to be divisible by 128 in cloudapi/compute and cloudbroker/compute
- Add field NumaNodeId in models RecordCompute and ItemCompute in cloudapi/compute and cloudbroker/compute
- Add BootDiskSet endpoints in cloudapi/compute and cloudbroker/compute
- Add endpoints DiskSwitchToReplication, DiskMigrate in cloudapi/compute and cloudbroker/compute
- Add field Replication in model RecordCompute.Disks.ItemComputeDisk in cloudapi/compute and cloudbroker/compute
- Add endpoint getCustomFields in cloudbroker/compute
- Delete field AffinityLabel in model AffinityRelationsRequest in cloudbroker/compute
- Add fields ImageName and VirtualImageName, delete VINSConnected fields in RecordCompute model in cloudbroker/compute
- Add fields Enabled and NodeID in ItemInterface model in cloudbroker/compute. Add NodeID field in ItemVNFInterface model in cloudapi/compute
#### disks:
- Add endpoints Replicate, ReplicationResume, ReplicationReverse, ReplicationStart, ReplicationStop, ReplicationStatus, ReplicationSuspend in cloudapi/disks and cloudbroker/disks
- Add field Replication in models RecordDisk and ItemDisk in cloudapi/disks and cloudbroker/disks
- Add CreateTemplateFromBlank and CreateTemplateFromBlankAsync endpoints in cloudapi/compute and cloudbroker/compute
- Add fields Page and Size in model SearchRequest in cloudapi/disks
- Add FromPlatformDisk and FromPlatformDiskAsync endpoints in cloudapi/disks and cloudbroker/disks
#### flipgroup:
- Add fields ConnId, Status, AccountId to model ListRequest in cloudapi/flipgroup and cloudbroker/flipgroup
- Add SortBy field for list groups and validation functionality
#### grid:
- Add endpoints addCustomBackupPath, removeCustomBackupPath, setPasswordPolicy in cloudbroker/grid
#### image:
- Add field CdPresentedTo in model RecordImage in cloudapi/image cloudbroker/image
- Set field AccountId in CreateRequest in cloudapi/image as required
- Add endpoints GrantAccess, RevokeAccess in cloudbroker/image
- Add SortBy field for list groups and validation functionality
- Add field NetworkInterfaceNaming in model CreateRequest in cloudapi/image cloudbroker/image, in model EditRequest in cloudbroker/image, in models ItemImage and RecordImage in cloudapi/image and cloudbroker/image
- Add validation field NetworkInterfaceNaming in cloudapi/image cloudbroker/image
- Delete field GID in model CreateRequest in cloudapi/image
- Delete field Meta and Ckey in model and RecordImage in cloudbroker/image
- Add model ItemImage in cloudbroker/image
#### k8s:
- Add field LbSysctlParams in model CreateRequest in cloudapi/k8s/create and cloudbroker/k8s/create
- Add validation of RAM to be divisible by 128 in cloudapi/k8s and cloudbroker/k8s
- Set uint64 as MasterRAM and WorkerRAM types in CreateRequest struct in cloudapi/k8s and cloudbroker/k8s
#### kvmppc
- Add validation of RAM to be divisible by 128 in cloudapi/kvmppc and cloudbroker/kvmppc
- Add DataDisks field to CreateRequest and CreateBlankRequest in cloudapi/kvmppc and cloudbroker/kvmppc
- Add DataDisks field to MassCreateRequest in cloudbroker/kvmppc
#### kvmx86
- Add validation of RAM to be divisible by 128 in cloudapi/kvmx86 and cloudbroker/kvmx86
- Add DataDisks field to CreateRequest and CreateBlankRequest in cloudapi/kvmx86 and cloudbroker/kvmx86
- Add DataDisks field to MassCreateRequest in cloudbroker/kvmx86
#### lb:
- Add fields UserManaged, ManagerId, ManagerType, PartK8S in models RecordLB, ItemLBList in cloudapi/lb and cloudbroker/lb
- Add SortBy field for list groups and validation functionality
- Add field SysctlParams in model CreateRequest in cloudapi/lb/create and cloudbroker/lb/create
- Add endpoint update_sysctl_params in cloudapi/lb and cloudbroker/lb
#### node:
- Add ApplyIpmiAction, Consumption, Decommission, Enable, EnableNodes, Get, GetRaw, List, ListRaw, Maintenance, Restrict, SetCoreIsolation, SetHugePages, SetSRIOVStatus, SetVFSNumber and Update endpoints in cloudbroker/node
- Add IDs method and Filters methods for ListNodes structure in cloudbroker/node
- Add Serialize method for ListNodes, ItemNode and RecordNode structures in cloudbroker/node
#### pcidevice:
- Add List, ListRaw endpoints in cloudapi/pcidevice
- Add IDs and Serialize methods for ListPCIDevices structure in cloudapi/pcidevice
#### rg:
- Add ComputeFeatures field to ItemResourceGroup and RecordResourceGroup models in cloudapi/rg
- Add ComputeFeatures field to ItemRG and CreateRequest models in cloudbroker/rg
- Add UpdateComputeFeatures endpoint in cloudbroker/rg
- Add ExtnetId, FreeIPs fields to model ItemVINS in cloudapi/rg and cloudbroker/rg
#### sep:
- Add endpoints addPool, delPool in cloudbroker/sep
- Set field Config in CreateRequest as required in cloudbroker/sep
- Add SortBy field for list groups and validation functionality
#### stack:
- Add endpoints getLogicalCoresCount, setCpuAllocationRatio, setMemAllocationRatio in cloudbroker/stack
#### tasks:
- Add field TaskId, Status, Completed in model ListRequest in cloudapi/task and cloudbroker/task
- Add fields GUID, UpdatedBy in model ItemTask in cloudapi/task and cloudbroker/task
- Fix panic in List endpoints in cloudapi/task and cloudbroker/task
- Change type field Result from int to interface{} in models RecordAsyncTask, ItemAsyncTask in cloudapi/task and models ItemTask, RecordTask in cloudbroker/task
- Add methods ID(), Name(), ToString(), ToMaps() for processing the value of the Result field in model ItemTask in cloudapi/task and cloudbroker/task
- Add use case examples for the above methods in README.md
- Add SortBy field for list groups and validation functionality
- Add fields UpdateTimeAt and UpdateTimeTo in model ListRequest in cloudapi/tasks and cloudbroker/tasks
#### user:
- Add fields Call, StatusCode, TimestampAt, TimestampTo in models GetAuditRequest in cloudbroker/user
- Fix return value in GetAudit endpoint in cloudbroker/user
- Add model ListAudits and change type field APIAccess in model ItemUser in cloudbroker/user
- Add SortBy field for list groups and validation functionality in cloudbroker/user
- Add APIList, Authenticate, Brief, GetAudit, GetResourceConsumption, Get, GetRaw, IsValidInviteUserToken, Search, SetData endpoints in cloudapi/user
#### vfpool:
- Add Get, GetRaw, List, ListRaw endpoints in cloudapi/vfpool
- Add Create, Delete, Disable, Enable, Get, GetRaw, List, ListRaw, Update endpoints in cloudbroker/vfpool
- Add IDs method for ListVFPool, VFSInfoListand in cloudapi/vfpool and cloudbroker/vfpool
- Add Filters methods for ListVFPool structure in cloudapi/vfpool and cloudbroker/vfpool
- Add Serialize method for ListVFPool, ItemVFPool and RecordVFPool structures in cloudapi/vfpool and cloudbroker/vfpool
#### vins:
- Set field IntPort in model NATRuleAddRequest as optional in cloudapi/vins and cloudbroker/vins
- Add SortBy field for list groups and validation functionality
- Add ExtnetId, FreeIPs fields to model ItemVINS in cloudapi/vins and cloudbroker/vins
- Add DNSList field to models CreateInAccountRequest and CreateInRGRequest in cloudapi/vins and cloudbroker/vins
- Add DNSApply endpoints in cloudapi/vins and cloudbroker/vins
- Add field NodeID in model RecordVINS.RecordVNFDev.Interfaces in cloudapi/vins and cloudbroker/vins
- Add NumaAffinity, CPUPin and HPBacked fields to model CreateRequest in cloudapi/kvmx86 and cloudbroker/kvmx86
- Add NumaAffinity, CPUPin and HPBacked fields to model UpdateRequest in cloudapi/compute and cloudbroker/compute
- Add ReservedNodeCpus field to models ItemCompute, RecordCompute in cloudapi/compute and to models ItemCompute, InfoCompute in cloudbroker/compute
- Add VFNIC as possible NetType value in Interfaces field in model CreateRequest in cloudapi/kvmx86 and cloudbroker/kvmx86
- Add VFNIC as possible NetType value in model NetAttachRequest in cloudapi/compute and cloudbroker/compute
- Add WithoutBootDisk field to models CreateRequest, CreateBlankRequest, MassCreateRequest in cloudapi/kvmx86 and cloudbroker/kvmx86
- Set optional fields BootDisk, SEPID, Pool in model CreateBlankRequest in cloudapi/kvmx86 and cloudbroker/kvmx86
- Set optional field ImageID in model CreateRequest in cloudapi/kvmx86 and cloudbroker/kvmx86
- Add field VNFDevID in models ListRequest (cloudbrocker/vins/list) and ListDeletedRequest (cloudapi/vins/list_deleted)
- Add new endpoints /cloudbroker/disks/present and /cloudbroker/disks/depresent
- Add field AuditID in model ListRequest (cloudbrocker/tasks/list, cloudapi/tasks/list)
- Add field ClientIDs in model ListRequest (cloudbrocker/flipgroup/list, cloudapi/flipgroup/list)
- Add field Depresent in model StopRequest (cloudbrocker/compute/stop)
- Add new endpoint /cloudbroker/image/uploadImageFile
### Bugfix
#### account:
- Fix wrong json, url field AccountID in model SetCPUAllocationParameterRequest in cloudbroker/account
- Fix wrong json, url field AccountID in model SetCPUAllocationRatioRequest in cloudbroker/account
- Change Start and End fields type from uint64 to float64 in model GetConsumptionRequest in cloudapi/account
#### apiaccess:
- Changed Job and Resmon field types in model CloudBrokerEndpoints in cloudbroker/apiaccess
- Add fields Page and Size in model UserListRequest in cloudbroker/apiaccess
#### bservice:
- Fix url for Disable endpoint in cloudapi/bservice
#### compute:
- Fix Entrycount tag in model ListComputes in cloudbroker/compute
- Add field Name in model ListPCIDeviceRequest in cloudbroker/compute
- Fix type of field Data in model ListPCIDevices in cloudapi/compute
- Add model ItemPCIDevice in cloudapi/compute
- Fix type of field Data in model ListVGPUs in cloudapi/compute and cloudbroker/compute
- Add model ItemVGPU in cloudapi/compute and cloudbroker/compute
#### disks:
- Delete tag required from field Detailed in ListTypesRequest model in cloudapi/disks
#### grid:
- Fix json, url tags in field Name in model RenameRequest in cloudbroker/grid
#### image:
- Fix url for ComputeCIUnset endpoint in cloudbroker/image
#### k8ci:
- Delete omitempty from json, url tags in field Permanently in model DeleteRequest in cloudbroker/k8ci
- Fix wrong json, url tags field ByID in model ListDeletedRequest in cloudbroker/k8ci
- Fix allowed network plugin value from "weawenet" to "weavenet" in validators for cloudbroker/k8ci
#### k8s:
- Fix allowed network plugin value from "weawenet" to "weavenet" in validators for cloudapi/k8s, cloudbroker/k8s
#### lb:
- Fix wrong json, url tags field AccountID in model ListDeletedRequest in cloudapi/lb
- Add field Safe in model RestartRequest in cloudbroker/lb
- Fix wrong json, url tags field AccountID in models ListRequest, ListDeletedRequest in cloudbroker/lb
- Fix url for Stop endpoint in cloudapi/lb
#### rg:
- Fix wrong json, url field AccountID in model ListLBRequest in cloudapi/rg and cloudbroker/rg
- Fix wrong json, url field UniqPools in model CreateRequest in cloudbroker/rg
#### sep:
- Fix wrong json, url tag in field GID in model ListRequest in cloudbroker/sep
#### user:
- Fix wrong json, url field Password in model ItemUser in cloudbroker/user
- Change ByID field type from uint64 to string in model ListRequest in cloudbroker/user
#### vins:
- Fix wrong json, url tags in models DefaultQOSUpdateRequest and NetQOSRequest in field IngressBirst in cloudbroker/vins
- Fix wrong name field ListNatRule to ListNATRule in cloudbroker/vins
- Change the return value of the method ReplicationStatus from interface to string in cloudapi/disks and cloudbroker/disks
- Fix type field Replication in models ItemComputeDisk (cloudapi/compute), ItemDisk (cloudapi/disks, cloudbroker/disks), RecordDisk (cloudapi/disks), InfoDisk (cloudbroker/compute). Add type ItemReplication in models cloudapi/disks, cloudbroker/disks, cloudapi/compute, cloudbroker/compute
- Rename field Async to AsyncMode in cloudapi/compute, cloudbroker/compute, cloudbroker/backup
- Fix url tags in fields UpdateTimeAt and UpdateTimeTo in models ListRequest (cloudapi/tasks/list, cloudbroker/tasks/list)
- Fix type field Completed in models ListRequest (cloudapi/tasks/list, cloudbroker/tasks/list)
- Fix type field Shared in models ListRequest (cloudapi/disk/list, cloudbroker/disk/list)
- Fix type field Shared in models ListDeletedRequest (cloudapi/disk/list_deleted, cloudbroker/disk/list_deleted)
- Fix type field Public, HotResize, Bootable in models ListRequest (cloudapi/image/list, cloudbroker/image/list)
- Fix type field Active, ServiceAccount in model ListRequest (cloudbroker/user/list)
- Change required type and correct description in field ImageID in model MassCreateRequest (cloudbroker/kvmx86/mass_create)
- Delete field AccountID in model ListLBRequest (cloudbroker/rg/listLB, cloudapi/rg/listLB)

@ -18,6 +18,7 @@ import (
"github.com/google/go-querystring/query"
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
)
@ -71,12 +72,22 @@ func (dc *DecortClient) CloudBroker() *cloudbroker.CloudBroker {
// DecortApiCall method for sending requests to the platform
func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
var body *bytes.Buffer
var ctype string
byteSlice, ok := params.([]byte)
if ok {
body = bytes.NewBuffer(byteSlice)
// ctype = "application/x-iso9660-image"
ctype = "application/octet-stream"
} else {
values, err := query.Values(params)
if err != nil {
return nil, err
}
body := bytes.NewBufferString(values.Encode())
body = bytes.NewBufferString(values.Encode())
}
req, err := http.NewRequestWithContext(ctx, method, dc.decortURL+constants.RESTMACHINE+url, body)
if err != nil {
@ -87,9 +98,8 @@ func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, p
if err = dc.getToken(ctx); err != nil {
return nil, err
}
// perform request
respBytes, err := dc.do(req, "")
respBytes, err := dc.do(req, ctype)
if err != nil {
return nil, err
}
@ -284,12 +294,23 @@ func multiPartReq(params interface{}) (*bytes.Buffer, string, error) {
if values.Field(i).Type().Kind() == reflect.Slice {
switch slice := values.Field(i).Interface().(type) {
case []string:
if validators.IsInSlice(trimString(types.Field(i)), constants.K8sValues) {
code, err := json.Marshal(slice)
if err != nil {
return &bytes.Buffer{}, "", err
}
err = writer.WriteField(trimString(types.Field(i)), string(code))
if err != nil {
return &bytes.Buffer{}, "", err
}
} else {
for _, val := range slice {
err := writer.WriteField(trimString(types.Field(i)), val)
if err != nil {
return &bytes.Buffer{}, "", err
}
}
}
case []uint:
for _, val := range slice {
err := writer.WriteField(trimString(types.Field(i)), strconv.FormatUint(uint64(val), 10))

@ -71,12 +71,21 @@ func (bdc *BVSDecortClient) CloudBroker() *cloudbroker.CloudBroker {
// DecortApiCall method for sending requests to the platform
func (bdc *BVSDecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
var body *bytes.Buffer
var ctype string
byteSlice, ok := params.([]byte)
if ok {
body = bytes.NewBuffer(byteSlice)
// ctype = "application/x-iso9660-image"
ctype = "application/octet-stream"
} else {
values, err := query.Values(params)
if err != nil {
return nil, err
}
body := bytes.NewBufferString(values.Encode())
body = bytes.NewBufferString(values.Encode())
}
req, err := http.NewRequestWithContext(ctx, method, bdc.decortURL+constants.RESTMACHINE+url, body)
if err != nil {
@ -101,7 +110,7 @@ func (bdc *BVSDecortClient) DecortApiCall(ctx context.Context, method, url strin
// perform request
reqCopy := req.Clone(ctx)
respBytes, err := bdc.do(req, "")
respBytes, err := bdc.do(req, ctype)
if err == nil {
return respBytes, nil
}

@ -10,3 +10,5 @@ const (
var FileName = map[string]string{
"OidcCertificate": "ca.crt",
}
var K8sValues = []string{"labels", "taints", "annotations, additionalSANs"}

@ -3,6 +3,7 @@ package validators
import (
"errors"
"fmt"
"reflect"
"regexp"
"strings"
@ -104,6 +105,13 @@ func computeNetTypeValidator(fe validator.FieldLevel) bool {
return IsInSlice(fieldValue, computeNetTypeValues)
}
// computex86NetTypeValidator is used to validate NetType field.
func computex86NetTypeValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, computex86NetTypeValues)
}
// computeOrderValidator is used to validate Order field.
func computeOrderValidator(fe validator.FieldLevel) bool {
fieldSlice, ok := fe.Field().Interface().([]string)
@ -312,6 +320,23 @@ func networkInterfaceNamingValidator(fe validator.FieldLevel) bool {
return IsInSlice(fieldValue, networkInterfaceNamingValues)
}
func numaAffinityValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, numaAffinityValues)
}
// kvmx86NetTypeValidator is used to validate NetType field for x86 compute.
func kvmx86NetTypeValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, kvmx86NetTypeValues)
}
func isBoolTypeValidator(fe validator.FieldLevel) bool {
return fe.Field().CanConvert(reflect.TypeOf(true))
}
// ValidateRAM checks if request contains RAM value that is positive integer divisible by divisibility passed.
// It is recommended to pass constants.RAM_DIVISIBILITY as divisility arguement
func ValidateRAM(r interfaces.RequestWithRAM, divisibility uint64) error {

@ -95,6 +95,12 @@ func errorMessage(fe validator.FieldError) string {
fe.Field(),
joinValues(computeNetTypeValues))
case "computex86NetType":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(computex86NetTypeValues))
case "computeOrder":
return fmt.Sprintf("%s %s can contain only the following values: %s",
prefix,
@ -258,6 +264,18 @@ func errorMessage(fe validator.FieldError) string {
prefix,
fe.Field(),
joinValues(networkInterfaceNamingValues))
case "numaAffinity":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(numaAffinityValues))
case "kvmx86NetType":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(kvmx86NetTypeValues))
}
return fe.Error()

@ -106,6 +106,11 @@ func registerAllValidators(validate *validator.Validate) error {
return err
}
err = validate.RegisterValidation("computex86NetType", computex86NetTypeValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("computeOrder", computeOrderValidator)
if err != nil {
return err
@ -211,5 +216,20 @@ func registerAllValidators(validate *validator.Validate) error {
return err
}
err = validate.RegisterValidation("numaAffinity", numaAffinityValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("kvmx86NetType", kvmx86NetTypeValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("isBool", isBoolTypeValidator)
if err != nil {
return err
}
return nil
}

@ -15,6 +15,7 @@ var (
computeModeValues = []string{"EQ", "EN", "ANY"}
computeDiskTypeValues = []string{"D", "B"}
computeNetTypeValues = []string{"EXTNET", "VINS"}
computex86NetTypeValues = []string{"EXTNET", "VINS", "VFNIC"}
computeOrderValues = []string{"cdrom", "network", "hd"}
computeDataDisksValues = []string{"KEEP", "DETACH", "DESTROY"}
computeDriverValues = []string{"KVM_X86", "SVA_KVM_X86"}
@ -24,6 +25,7 @@ var (
flipgroupClientTypeValues = []string{"compute", "vins"}
kvmNetTypeValues = []string{"EXTNET", "VINS", "NONE"}
kvmx86NetTypeValues = []string{"EXTNET", "VINS", "NONE", "VFNIC"}
lbAlgorithmValues = []string{"roundrobin", "static-rr", "leastconn"}
@ -52,4 +54,6 @@ var (
computeFeaturesValues = []string{"hugepages", "numa", "cpupin", "vfnic"}
networkInterfaceNamingValues = []string{"eth", "ens"}
numaAffinityValues = []string{"none", "strict", "loose"}
)

@ -73,12 +73,20 @@ func (ldc *LegacyDecortClient) DecortApiCall(ctx context.Context, method, url st
return nil, err
}
var body *bytes.Buffer
var ctype string
byteSlice, ok := params.([]byte)
if ok {
body = bytes.NewBuffer(byteSlice)
ctype = "application/octet-stream"
} else {
values, err := query.Values(params)
if err != nil {
return nil, err
}
body := bytes.NewBufferString(values.Encode() + fmt.Sprintf("&authkey=%s", ldc.cfg.Token))
body = bytes.NewBufferString(values.Encode() + fmt.Sprintf("&authkey=%s", ldc.cfg.Token))
}
req, err := http.NewRequestWithContext(ctx, method, ldc.decortURL+constants.RESTMACHINE+url, body)
if err != nil {
@ -86,7 +94,7 @@ func (ldc *LegacyDecortClient) DecortApiCall(ctx context.Context, method, url st
}
// perform request
respBytes, err := ldc.do(req, "")
respBytes, err := ldc.do(req, ctype)
if err != nil {
return nil, err
}

@ -23,7 +23,7 @@ type CreateTemplateRequest struct {
type wrapperCreateTemplateRequest struct {
CreateTemplateRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// CreateTemplate create template from compute instance
@ -35,7 +35,7 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest)
reqWrapped := wrapperCreateTemplateRequest{
CreateTemplateRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudapi/compute/createTemplate"
@ -62,7 +62,7 @@ func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequ
reqWrapped := wrapperCreateTemplateRequest{
CreateTemplateRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudapi/compute/createTemplate"

@ -431,6 +431,9 @@ type RecordCompute struct {
// Resource name
ResName string `json:"resName"`
// Reserved Node Cpus
ReservedNodeCpus []uint64 `json:"reservedNodeCpus"`
// Resource group ID
RGID uint64 `json:"rgId"`
@ -673,7 +676,7 @@ type ItemComputeDisk struct {
RealityDeviceNumber uint64 `json:"realityDeviceNumber"`
// Replication
Replication interface{} `json:"replication"`
Replication ItemReplication `json:"replication"`
// Resource ID
ResID string `json:"resId"`
@ -709,6 +712,26 @@ type ItemComputeDisk struct {
VMID uint64 `json:"vmid"`
}
type ItemReplication struct {
// DiskID
DiskID uint64 `json:"diskId"`
// PoolID
PoolID string `json:"poolId"`
// Role
Role string `json:"role"`
// SelfVolumeID
SelfVolumeID string `json:"selfVolumeId"`
// StorageID
StorageID string `json:"storageId"`
// VolumeID
VolumeID string `json:"volumeId"`
}
// Main information about snapshot extend
type SnapshotExtend struct {
// GUID
@ -915,6 +938,9 @@ type ItemCompute struct {
// Resource name
ResName string `json:"resName"`
// Reserved Node Cpus
ReservedNodeCpus []uint64 `json:"reservedNodeCpus"`
// Resource group ID
RGID uint64 `json:"rgId"`
@ -1085,6 +1111,7 @@ type ItemPCIDevice struct {
type ListPCIDevices struct {
// Data
Data []ItemPCIDevice `json:"data"`
// Entry count
EntryCount uint64 `json:"entryCount"`
}

@ -16,9 +16,10 @@ type NetAttachRequest struct {
// Network type
// 'EXTNET' for connect to external network directly
// and 'VINS' for connect to ViNS
// 'VINS' for connect to ViNS
// 'VFNIC' for connect to vfpool
// Required: true
NetType string `url:"netType" json:"netType" validate:"computeNetType"`
NetType string `url:"netType" json:"netType" validate:"computex86NetType"`
// Network ID for connect to
// For EXTNET - external network ID

@ -21,6 +21,24 @@ type UpdateRequest struct {
// New description
// Required: false
Description string `url:"desc,omitempty" json:"desc,omitempty"`
// Rule for VM placement with NUMA affinity.
// Possible values - none (placement without NUMA affinity),
// strict (strictly with NUMA affinity, if not possible - do not start VM),
// loose (use NUMA affinity if possible)
// Required: false
// Default: none
NumaAffinity string `url:"numaAffinity,omitempty" json:"numaAffinity,omitempty" validate:"omitempty,numaAffinity"`
// Run VM on dedicated CPUs. To use this feature, the system must be pre-configured by allocating CPUs on the physical node
// Required: false
// Default: false
CPUPin bool `url:"cpupin" json:"cpupin"`
// Use Huge Pages to allocate RAM of the virtual machine. The system must be pre-configured by allocating Huge Pages on the physical node
// Required: false
// Default: false
HPBacked bool `url:"hpBacked" json:"hpBacked"`
}
// Update updates some properties of the compute

@ -57,7 +57,7 @@ type FromPlatformDiskRequest struct {
// List of types of compute suitable for image
// Example: [ "KVM_X86" ]
// Required: false
Drivers []string `url:"drivers" json:"drivers" validate:"min=1,max=2,imageDrivers"`
Drivers []string `url:"drivers,omitempty" json:"drivers,omitempty"`
// Does this machine supports hot resize
// Required: false

@ -32,7 +32,7 @@ type ListRequest struct {
// Find by shared, true or false
// Required: false
Shared bool `url:"shared,omitempty" json:"shared,omitempty"`
Shared interface{} `url:"shared,omitempty" json:"shared,omitempty" validate:"omitempty,isBool"`
// ID of the account the disks belong to
// Required: false

@ -28,7 +28,7 @@ type ListDeletedRequest struct {
// Find by shared, true or false
// Required: false
Shared bool `url:"shared,omitempty" json:"shared,omitempty"`
Shared interface{} `url:"shared,omitempty" json:"shared,omitempty" validate:"omitempty,isBool"`
// ID of the account the disks belong to
// Required: false

@ -75,7 +75,7 @@ type ItemDisk struct {
PurgeTime uint64 `json:"purgeTime"`
// Replication
Replication interface{} `json:"replication"`
Replication ItemReplication `json:"replication"`
// Resource ID
ResID string `json:"resId"`
@ -265,8 +265,10 @@ type ListDisks struct {
// List of unattached disks
type ListDisksUnattached struct {
// Data
Data []ItemDiskUnattached `json:"data"`
// Entry count
EntryCount uint64 `json:"entryCount"`
}
@ -407,7 +409,7 @@ type RecordDisk struct {
PurgeTime uint64 `json:"purgeTime"`
// Replication
Replication interface{} `json:"replication"`
Replication ItemReplication `json:"replication"`
// Resource ID
ResID string `json:"resId"`
@ -449,6 +451,26 @@ type RecordDisk struct {
VMID uint64 `json:"vmid"`
}
type ItemReplication struct {
// DiskID
DiskID uint64 `json:"diskId"`
// PoolID
PoolID string `json:"poolId"`
// Role
Role string `json:"role"`
// SelfVolumeID
SelfVolumeID string `json:"selfVolumeId"`
// StorageID
StorageID string `json:"storageId"`
// VolumeID
VolumeID string `json:"volumeId"`
}
type ListTypes struct {
// Data
Data []interface{} `json:"data"`

@ -15,23 +15,18 @@ type ReplicationStatusRequest struct {
}
// ReplicationStatus get replication status
func (d Disks) ReplicationStatus(ctx context.Context, req ReplicationStatusRequest) (interface{}, error) {
func (d Disks) ReplicationStatus(ctx context.Context, req ReplicationStatusRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
return "", validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/disks/replicationStatus"
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return nil, err
return "", err
}
// result, err := strconv.ParseBool(string(res))
// if err != nil {
// return nil, err
// }
return res, nil
return string(res), nil
}

@ -42,6 +42,10 @@ type ListRequest struct {
// Required: false
ByID uint64 `url:"by_id,omitempty" json:"by_id,omitempty"`
// Find by list of clientIds
// Required: false
ClientIDs []uint64 `url:"clientIds,omitempty" json:"clientIds,omitempty"`
// Page number
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -48,15 +48,15 @@ type ListRequest struct {
// Find by public True or False
// Required: false
Public bool `url:"public,omitempty" json:"public,omitempty"`
Public interface{} `url:"public,omitempty" json:"public,omitempty" validate:"omitempty,sortBy"`
// Find by hot resize True or False
// Required: false
HotResize bool `url:"hotResize,omitempty" json:"hotResize,omitempty"`
HotResize interface{} `url:"hotResize,omitempty" json:"hotResize,omitempty" validate:"omitempty,sortBy"`
// Find by bootable True or False
// Required: false
Bootable bool `url:"bootable,omitempty" json:"bootable,omitempty"`
Bootable interface{} `url:"bootable,omitempty" json:"bootable,omitempty" validate:"omitempty,sortBy"`
// Sort by one of supported fields, format +|-(field)
// Required: false

@ -14,7 +14,8 @@ type Interface struct {
// Should be one of:
// - VINS
// - EXTNET
NetType string `url:"netType" json:"netType" validate:"required,kvmNetType"`
// - VFNIC
NetType string `url:"netType" json:"netType" validate:"required,kvmx86NetType"`
// Network ID for connect to,
// for EXTNET - external network ID,
@ -74,10 +75,14 @@ type CreateRequest struct {
// Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
// ID of the OS image to base this VM on;
// Could be boot disk image or CD-ROM image
// Required: true
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
// Required: false
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
// Size of the boot disk in GB
// Required: false
@ -131,6 +136,24 @@ type CreateRequest struct {
// Type of compute Stateful (KVM_X86) or Stateless (SVA_KVM_X86)
// Required: false
Driver string `url:"driver,omitempty" json:"driver,omitempty" validate:"omitempty,computeDriver"`
// Rule for VM placement with NUMA affinity.
// Possible values - none (placement without NUMA affinity),
// strict (strictly with NUMA affinity, if not possible - do not start VM),
// loose (use NUMA affinity if possible)
// Required: false
// Default: none
NumaAffinity string `url:"numaAffinity,omitempty" json:"numaAffinity,omitempty" validate:"omitempty,numaAffinity"`
// Run VM on dedicated CPUs. To use this feature, the system must be pre-configured by allocating CPUs on the physical node
// Required: false
// Default: false
CPUPin bool `url:"cpupin" json:"cpupin"`
// Use Huge Pages to allocate RAM of the virtual machine. The system must be pre-configured by allocating Huge Pages on the physical node
// Required: false
// Default: false
HPBacked bool `url:"hpBacked" json:"hpBacked"`
}
// GetRAM returns RAM field values

@ -28,18 +28,22 @@ type CreateBlankRequest struct {
// Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
// Size of the boot disk in GB
// Required: true
BootDisk uint64 `url:"bootDisk" json:"bootDisk" validate:"required"`
// Required: false
BootDisk uint64 `url:"bootDisk,omitempty" json:"bootDisk,omitempty"`
// ID of SEP to create boot disk on.
// Uses images SEP ID if not set
// Required: true
SEPID uint64 `url:"sepId" json:"sepId" validate:"required"`
// Required: false
SEPID uint64 `url:"sepId,omitempty" json:"sepId,omitempty"`
// Pool to use if sepId is set, can be also empty if needed to be chosen by system
// Required: true
Pool string `url:"pool" json:"pool" validate:"required"`
// Required: false
Pool string `url:"pool,omitempty" json:"pool,omitempty"`
// Slice of structs with data disk description. Each disk has parameters: required - diskName, size; optional - sepId, pool, desc and imageId.
// If not specified, compute will be created without disks.

@ -22,10 +22,6 @@ type ListLBRequest struct {
// Required: false
Name string `url:"name,omitempty" json:"name,omitempty"`
// Find by account ID
// Required: false
AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"`
// Find by tech status
// Required: false
TechStatus string `url:"techStatus,omitempty" json:"techStatus,omitempty"`

@ -14,14 +14,17 @@ type ListRequest struct {
// Required: false
TaskID string `url:"taskId,omitempty" json:"taskId,omitempty"`
// Find by auditId
// Required: false
AuditID string `url:"auditId,omitempty" json:"auditId,omitempty"`
// Find by status
// Required: false
Status string `url:"status,omitempty" json:"status,omitempty"`
// Find by completed True or False
// Default: false
// Required: false
Completed bool `url:"completed" json:"completed"`
Completed interface{} `url:"completed,omitempty" json:"completed,omitempty" validate:"omitempty,isBool"`
// Sort by one of supported fields, format +|-(field)
// Required: false
@ -29,19 +32,21 @@ type ListRequest struct {
// Find all tasks after point in time (unixtime)
// Required: false
UpdateTimeAt uint64 `url:"page,updateTimeAt" json:"updateTimeAt,omitempty"`
UpdateTimeAt uint64 `url:"updateTimeAt,omitempty" json:"updateTimeAt,omitempty"`
// Find all tasks before point in time (unixtime)
// Required: false
UpdateTimeTo uint64 `url:"page,updateTimeTo" json:"updateTimeTo,omitempty"`
UpdateTimeTo uint64 `url:"updateTimeTo,omitempty" json:"updateTimeTo,omitempty"`
// Page number
// Default: 0
// Default: 0
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
// Page size
// Default: 0
// Default: 0
// Required: false
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
}
@ -71,6 +76,10 @@ func (t Tasks) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
if err := validators.ValidateRequest(req); err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/tasks/list"
res, err := t.client.DecortApiCall(ctx, http.MethodPost, url, req)

@ -30,6 +30,10 @@ type ListDeletedRequest struct {
// Required: false
ExtIP string `url:"extIp,omitempty" json:"extIp,omitempty"`
// Find by VNF Device id
// Required: false
VNFDevID uint64 `url:"vnfdevId,omitempty" json:"vnfdevId,omitempty"`
// Sort by one of supported fields, format +|-(field)
// Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
@ -50,6 +54,10 @@ func (v VINS) ListDeleted(ctx context.Context, req ListDeletedRequest) (*ListVIN
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
if err := validators.ValidateRequest(req); err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/vins/listDeleted"
res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req)

@ -27,7 +27,7 @@ type CreateDiskBackupRequest struct {
type wrapperCreateDiskBackupRequest struct {
CreateDiskBackupRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// CreateDiskBackup creates disk backup
@ -39,7 +39,7 @@ func (b Backup) CreateDiskBackup(ctx context.Context, req CreateDiskBackupReques
reqWrapped := wrapperCreateDiskBackupRequest{
CreateDiskBackupRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudbroker/backup/createDiskBackup"
@ -68,7 +68,7 @@ func (b Backup) CreateDiskBackupAsync(ctx context.Context, req CreateDiskBackupR
reqWrapped := wrapperCreateDiskBackupRequest{
CreateDiskBackupRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudbroker/backup/createDiskBackup"

@ -29,7 +29,7 @@ type CreateDisksBackupRequest struct {
type wrapperCreateDisksBackupRequest struct {
CreateDisksBackupRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// CreateDisksBackup creates disks backup
@ -41,7 +41,7 @@ func (b Backup) CreateDisksBackup(ctx context.Context, req CreateDisksBackupRequ
reqWrapped := wrapperCreateDisksBackupRequest{
CreateDisksBackupRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudbroker/backup/createDisksBackup"
@ -70,7 +70,7 @@ func (b Backup) CreateDisksBackupAsync(ctx context.Context, req CreateDisksBacku
reqWrapped := wrapperCreateDisksBackupRequest{
CreateDisksBackupRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudbroker/backup/createDisksBackup"

@ -21,7 +21,7 @@ type DeleteDiskBackupRequest struct {
type wrapperDeleteDiskBackupRequest struct {
DeleteDiskBackupRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// DeleteDiskBackup deletes disk backup
@ -33,7 +33,7 @@ func (b Backup) DeleteDiskBackup(ctx context.Context, req DeleteDiskBackupReques
reqWrapped := wrapperDeleteDiskBackupRequest{
DeleteDiskBackupRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudbroker/backup/deleteDiskBackup"
@ -60,7 +60,7 @@ func (b Backup) DeleteDiskBackupAsync(ctx context.Context, req DeleteDiskBackupR
reqWrapped := wrapperDeleteDiskBackupRequest{
DeleteDiskBackupRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudbroker/backup/deleteDiskBackup"

@ -27,7 +27,7 @@ type RestoreDiskFromBackupRequest struct {
type wrapperRestoreDiskFromBackupRequest struct {
RestoreDiskFromBackupRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// RestoreDiskFromBackup restores disk from backup
@ -39,7 +39,7 @@ func (b Backup) RestoreDiskFromBackup(ctx context.Context, req RestoreDiskFromBa
reqWrapped := wrapperRestoreDiskFromBackupRequest{
RestoreDiskFromBackupRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudbroker/backup/restoreDiskFromBackup"
@ -68,7 +68,7 @@ func (b Backup) RestoreDiskFromBackupAsync(ctx context.Context, req RestoreDiskF
reqWrapped := wrapperRestoreDiskFromBackupRequest{
RestoreDiskFromBackupRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudbroker/backup/restoreDiskFromBackup"

@ -32,7 +32,7 @@ type RestoreDisksFromBackupRequest struct {
type wrapperRestoreDisksFromBackupRequest struct {
RestoreDisksFromBackupRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// RestoreDisksFromBackup restores disks from backup
@ -44,7 +44,7 @@ func (b Backup) RestoreDisksFromBackup(ctx context.Context, req RestoreDisksFrom
reqWrapped := wrapperRestoreDisksFromBackupRequest{
RestoreDisksFromBackupRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudbroker/backup/restoreDisksFromBackup"
@ -73,7 +73,7 @@ func (b Backup) RestoreDisksFromBackupAsync(ctx context.Context, req RestoreDisk
reqWrapped := wrapperRestoreDisksFromBackupRequest{
RestoreDisksFromBackupRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudbroker/backup/restoreDisksFromBackup"

@ -27,7 +27,7 @@ type CreateTemplateRequest struct {
type wrapperCreateTemplateRequest struct {
CreateTemplateRequest
Async bool `url:"async"`
AsyncMode bool `url:"asyncMode"`
}
// CreateTemplateAsync create template from compute instance
@ -39,7 +39,7 @@ func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequ
reqWrapped := wrapperCreateTemplateRequest{
CreateTemplateRequest: req,
Async: true,
AsyncMode: true,
}
url := "/cloudbroker/compute/createTemplate"
@ -63,7 +63,7 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest)
reqWrapped := wrapperCreateTemplateRequest{
CreateTemplateRequest: req,
Async: false,
AsyncMode: false,
}
url := "/cloudbroker/compute/createTemplate"

@ -440,7 +440,7 @@ type ItemDisk struct {
RealityDeviceNumber uint64 `json:"realityDeviceNumber"`
// Replication
Replication interface{} `json:"replication"`
Replication ItemReplication `json:"replication"`
// Reference ID
ReferenceID string `json:"referenceId"`
@ -485,6 +485,26 @@ type ItemDisk struct {
VMID uint64 `json:"vmid"`
}
type ItemReplication struct {
// DiskID
DiskID uint64 `json:"diskId"`
// PoolID
PoolID string `json:"poolId"`
// Role
Role string `json:"role"`
// SelfVolumeID
SelfVolumeID string `json:"selfVolumeId"`
// StorageID
StorageID string `json:"storageId"`
// VolumeID
VolumeID string `json:"volumeId"`
}
// List disks
type ListDisks []ItemDisk
@ -706,6 +726,9 @@ type InfoCompute struct {
// Resource name
ResName string `json:"resName"`
// Reserved Node Cpus
ReservedNodeCpus []uint64 `json:"reservedNodeCpus"`
// Resource group ID
RGID uint64 `json:"rgId"`
@ -919,6 +942,9 @@ type RecordCompute struct {
// Resource name
ResName string `json:"resName"`
// Reserved Node Cpus
ReservedNodeCpus []uint64 `json:"reservedNodeCpus"`
// Resource group ID
RGID uint64 `json:"rgId"`
@ -1010,6 +1036,7 @@ type ListComputes struct {
EntryCount uint64 `json:"entryCount"`
}
// Short information about audit
// Short information about audit
type ItemAudit struct {
// Epoch

@ -16,9 +16,10 @@ type NetAttachRequest struct {
// Network type
// 'EXTNET' for connect to external network directly
// and 'VINS' for connect to ViNS
// 'VINS' for connect to ViNS
// 'VFNIC' for connect to vfpool
// Required: true
NetType string `url:"netType" json:"netType" validate:"computeNetType"`
NetType string `url:"netType" json:"netType" validate:"computex86NetType"`
// Network ID for connect to
// For EXTNET - external network ID

@ -18,6 +18,11 @@ type StopRequest struct {
// Required: false
Force bool `url:"force,omitempty" json:"force,omitempty"`
// whether to depresent compute disks from node or not
// Default: true
// Required: false
Depresent bool `url:"depresent" json:"depresent"`
// Reason for action
// Required: false
Reason string `url:"reason,omitempty" json:"reason,omitempty"`

@ -22,6 +22,24 @@ type UpdateRequest struct {
// Required: false
Description string `url:"desc,omitempty" json:"desc,omitempty"`
// Rule for VM placement with NUMA affinity.
// Possible values - none (placement without NUMA affinity),
// strict (strictly with NUMA affinity, if not possible - do not start VM),
// loose (use NUMA affinity if possible)
// Required: false
// Default: none
NumaAffinity string `url:"numaAffinity,omitempty" json:"numaAffinity,omitempty" validate:"omitempty,numaAffinity"`
// Run VM on dedicated CPUs. To use this feature, the system must be pre-configured by allocating CPUs on the physical node
// Required: false
// Default: false
CPUPin bool `url:"cpupin" json:"cpupin"`
// Use Huge Pages to allocate RAM of the virtual machine. The system must be pre-configured by allocating Huge Pages on the physical node
// Required: false
// Default: false
HPBacked bool `url:"hpBacked" json:"hpBacked"`
// Reason for action
// Required: false
Reason string `url:"reason,omitempty" json:"reason,omitempty"`

@ -0,0 +1,41 @@
package disks
import (
"context"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
"strconv"
)
// DepresentRequest struct to depresent disk from node
type DepresentRequest struct {
// ID of the disk to depresent
// Required: true
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
// ID of the node to depresent disk from
// Required: true
NodeID uint64 `url:"nodeId" json:"nodeId" validate:"required"`
}
// Depresent depresents disk from node
func (d Disks) Depresent(ctx context.Context, req DepresentRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/disks/depresent"
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -57,7 +57,7 @@ type FromPlatformDiskRequest struct {
// List of types of compute suitable for image
// Example: [ "KVM_X86" ]
// Required: false
Drivers []string `url:"drivers" json:"drivers" validate:"min=1,max=2,imageDrivers"`
Drivers []string `url:"drivers,omitempty" json:"drivers,omitempty"`
// Does this machine supports hot resize
// Required: false

@ -32,7 +32,7 @@ type ListRequest struct {
// Find by shared, true or false
// Required: false
Shared bool `url:"shared,omitempty" json:"shared,omitempty"`
Shared interface{} `url:"shared,omitempty" json:"shared,omitempty" validate:"omitempty,isBool"`
// ID of the account the disks belong to
// Required: false

@ -28,7 +28,7 @@ type ListDeletedRequest struct {
// Find by shared, true or false
// Required: false
Shared bool `url:"shared,omitempty" json:"shared,omitempty"`
Shared interface{} `url:"shared,omitempty" json:"shared,omitempty" validate:"omitempty,isBool"`
// ID of the account the disks belong to
// Required: false

@ -138,7 +138,7 @@ type InfoDisk struct {
ReferenceID string `json:"referenceId"`
// Replication
Replication interface{} `json:"replication"`
Replication ItemReplication `json:"replication"`
// Resource ID
ResID string `json:"resId"`
@ -177,6 +177,26 @@ type InfoDisk struct {
VMID uint64 `json:"vmid"`
}
type ItemReplication struct {
// DiskID
DiskID uint64 `json:"diskId"`
// PoolID
PoolID string `json:"poolId"`
// Role
Role string `json:"role"`
// SelfVolumeID
SelfVolumeID string `json:"selfVolumeId"`
// StorageID
StorageID string `json:"storageId"`
// VolumeID
VolumeID string `json:"volumeId"`
}
// Detailed indormation about disk
type RecordDisk struct {
// Device name

@ -0,0 +1,41 @@
package disks
import (
"context"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
"strconv"
)
// PresentRequest struct to present disk to node
type PresentRequest struct {
// ID of the disk to present
// Required: true
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
// ID of the node to present disk to
// Required: true
NodeID uint64 `url:"nodeId" json:"nodeId" validate:"required"`
}
// Present presents disk to node
func (d Disks) Present(ctx context.Context, req PresentRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/disks/present"
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -15,23 +15,18 @@ type ReplicationStatusRequest struct {
}
// ReplicationStatus get replication status
func (d Disks) ReplicationStatus(ctx context.Context, req ReplicationStatusRequest) (interface{}, error) {
func (d Disks) ReplicationStatus(ctx context.Context, req ReplicationStatusRequest) (string, error) {
err := validators.ValidateRequest(req)
if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
return "", validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/disks/replicationStatus"
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return nil, err
return "", err
}
// result, err := strconv.ParseBool(string(res))
// if err != nil {
// return nil, err
// }
return res, nil
return string(res), nil
}

@ -42,6 +42,10 @@ type ListRequest struct {
// Required: false
ByID uint64 `url:"by_id,omitempty" json:"by_id,omitempty"`
// Find by list of clientIds
// Required: false
ClientIDs []uint64 `url:"clientIds,omitempty" json:"clientIds,omitempty"`
// Sort by one of supported fields, format +|-(field)
// Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
@ -88,6 +92,10 @@ func (f FLIPGroup) ListRaw(ctx context.Context, req ListRequest) ([]byte, error)
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
if err := validators.ValidateRequest(req); err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/flipgroup/list"
res, err := f.client.DecortApiCall(ctx, http.MethodPost, url, req)

@ -31,6 +31,7 @@ type ListRequest struct {
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
// Find by active True or False.
// Default: true
// Required: false
Active bool `url:"active" json:"active"`
}

@ -48,15 +48,15 @@ type ListRequest struct {
// Find by public True or False
// Required: false
Public bool `url:"public,omitempty" json:"public,omitempty"`
Public interface{} `url:"public,omitempty" json:"public,omitempty" validate:"omitempty,isBool"`
// Find by hot resize True or False
// Required: false
HotResize bool `url:"hotResize,omitempty" json:"hotResize,omitempty"`
HotResize interface{} `url:"hotResize,omitempty" json:"hotResize,omitempty" validate:"omitempty,isBool"`
// Find by bootable True or False
// Required: false
Bootable bool `url:"bootable,omitempty" json:"bootable,omitempty"`
Bootable interface{} `url:"bootable,omitempty" json:"bootable,omitempty" validate:"omitempty,isBool"`
// Sort by one of supported fields, format +|-(field)
// Required: false

@ -0,0 +1,39 @@
package image
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
)
// UploadImageFileResponse struct to enable image
type UploadImageFileResponse struct {
// ImageFileUri
ImageFileUri string `json:"image_file_uri"`
}
// UploadImageFile uploads file image to platform
func (i Image) UploadImageFile(ctx context.Context, filePath string) (string, error) {
file, err := os.ReadFile(filePath)
if err != nil {
return "", fmt.Errorf("can not read file %v", err)
}
url := "/cloudbroker/image/uploadImageFile"
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, file)
if err != nil {
return "", err
}
result := UploadImageFileResponse{}
err = json.Unmarshal(res, &result)
if err != nil {
return "", err
}
return result.ImageFileUri, nil
}

@ -14,7 +14,8 @@ type Interface struct {
// Should be one of:
// - VINS
// - EXTNET
NetType string `url:"netType" json:"netType" validate:"required,kvmNetType"`
// - VFNIC
NetType string `url:"netType" json:"netType" validate:"required,kvmx86NetType"`
// Network ID for connect to,
// for EXTNET - external network ID,
@ -74,10 +75,14 @@ type CreateRequest struct {
// Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
// ID of the OS image to base this VM on;
// Could be boot disk image or CD-ROM image
// Required: true
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
// Required: false
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
// Size of the boot disk in GB
// Required: false
@ -136,6 +141,24 @@ type CreateRequest struct {
// Required: false
Driver string `url:"driver,omitempty" json:"driver,omitempty"`
// Rule for VM placement with NUMA affinity.
// Possible values - none (placement without NUMA affinity),
// strict (strictly with NUMA affinity, if not possible - do not start VM),
// loose (use NUMA affinity if possible)
// Required: false
// Default: none
NumaAffinity string `url:"numaAffinity,omitempty" json:"numaAffinity,omitempty" validate:"omitempty,numaAffinity"`
// Run VM on dedicated CPUs. To use this feature, the system must be pre-configured by allocating CPUs on the physical node
// Required: false
// Default: false
CPUPin bool `url:"cpupin" json:"cpupin"`
// Use Huge Pages to allocate RAM of the virtual machine. The system must be pre-configured by allocating Huge Pages on the physical node
// Required: false
// Default: false
HPBacked bool `url:"hpBacked" json:"hpBacked"`
// Reason for action
// Required: false
Reason string `url:"reason,omitempty" json:"reason,omitempty"`

@ -28,18 +28,22 @@ type CreateBlankRequest struct {
// Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
// Size of the boot disk in GB
// Required: true
BootDisk uint64 `url:"bootDisk" json:"bootDisk" validate:"required"`
// Required: false
BootDisk uint64 `url:"bootDisk,omitempty" json:"bootDisk,omitempty"`
// ID of SEP to create boot disk on.
// Uses images SEP ID if not set
// Required: true
SEPID uint64 `url:"sepId" json:"sepId" validate:"required"`
// Required: false
SEPID uint64 `url:"sepId,omitempty" json:"sepId,omitempty"`
// Pool to use if sepId is set, can be also empty if needed to be chosen by system
// Required: true
Pool string `url:"pool" json:"pool" validate:"required"`
// Required: false
Pool string `url:"pool,omitempty" json:"pool,omitempty"`
// Slice of structs with data disk description. Each disk has parameters: required - diskName, size; optional - sepId, pool, desc and imageId.
// If not specified, compute will be created without disks.

@ -31,9 +31,13 @@ type MassCreateRequest struct {
// Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"`
// Image ID
// Required: true
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
// ID of the OS image to base this VM on; Could be boot disk image or CD-ROM image
// Required: false
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
// Size of the boot disk in GB
// Required: false

@ -102,7 +102,7 @@ type ConsumedResourcesInfo struct {
// Information about node CPU
type CpuInfo struct {
// Clock Speed
ClockSpeed uint64 `json:"clockSpeed"`
ClockSpeed float64 `json:"clockSpeed"`
// CoreCount
CoreCount uint64 `json:"coreCount"`

@ -22,10 +22,6 @@ type ListLBRequest struct {
// Required: false
Name string `url:"name,omitempty" json:"name,omitempty"`
// Find by account ID
// Required: false
AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"`
// Find by tech status
// Required: false
TechStatus string `url:"techStatus,omitempty" json:"techStatus,omitempty"`

@ -14,14 +14,17 @@ type ListRequest struct {
// Required: false
TaskID string `url:"taskId,omitempty" json:"taskId,omitempty"`
// Find by auditId
// Required: false
AuditID string `url:"auditId,omitempty" json:"auditId,omitempty"`
// Find by status
// Required: false
Status string `url:"status,omitempty" json:"status,omitempty"`
// Find by completed True or False
// Default: false
// Required: false
Completed bool `url:"completed" json:"completed"`
Completed interface{} `url:"completed,omitempty" json:"completed,omitempty" validate:"omitempty,isBool"`
// Sort by one of supported fields, format +|-(field)
// Required: false
@ -29,19 +32,21 @@ type ListRequest struct {
// Find all tasks after point in time (unixtime)
// Required: false
UpdateTimeAt uint64 `url:"page,updateTimeAt" json:"updateTimeAt,omitempty"`
UpdateTimeAt uint64 `url:"updateTimeAt,omitempty" json:"updateTimeAt,omitempty"`
// Find all tasks before point in time (unixtime)
// Required: false
UpdateTimeTo uint64 `url:"page,updateTimeTo" json:"updateTimeTo,omitempty"`
UpdateTimeTo uint64 `url:"updateTimeTo,omitempty" json:"updateTimeTo,omitempty"`
// Page number
// Default: 0
// Default: 0
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
// Page size
// Default: 0
// Default: 0
// Required: false
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
}

@ -16,11 +16,11 @@ type ListRequest struct {
// Find by active. True or False.
// Required: false
Active bool `url:"active,omitempty" json:"active,omitempty"`
Active interface{} `url:"active,omitempty" json:"active,omitempty" validate:"omitempty,isBool"`
// Find by serviceaccount. True or False.
// Required: false
ServiceAccount bool `url:"serviceaccount,omitempty" json:"serviceaccount,omitempty"`
ServiceAccount interface{} `url:"serviceaccount,omitempty" json:"serviceaccount,omitempty" validate:"omitempty,isBool"`
// Sort by one of supported fields, format +|-(field)
// Required: false

@ -15,8 +15,8 @@ type DNSApplyRequest struct {
VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"`
// List of DNS ip address
// Required: true
DNSList []string `url:"dnsList" json:"dnsList" validate:"required"`
// Required: false
DNSList []string `url:"dnsList" json:"dnsList"`
}
// DNSApply applies new DNS list in VINS

@ -30,6 +30,10 @@ type ListRequest struct {
// Required: false
ExtIP string `url:"extIp,omitempty" json:"extIp,omitempty"`
// Find by VNF Device id
// Required: false
VNFDevID uint64 `url:"vnfdevId,omitempty" json:"vnfdevId,omitempty"`
// Include deleted
// Required: false
IncludeDeleted bool `url:"includeDeleted,omitempty" json:"includeDeleted,omitempty"`

@ -17,7 +17,11 @@
1. Тесты находятся по директории `decort-sdk/tests/platform_upgrade`
2. Внутри директории нужно создать и заполнить файл `.env` по аналогии с `.env.template` для доступа к платформе
3. Внутри директории нужно создать и заполнить файл `input.json`, содержащий json с раздела [POST /system/docgenerator/prepareCatalog](https://delta.qa.loc/system/ActorApi?group=system#!/system__docgenerator/post_system_docgenerator_prepareCatalog) (для получения json нажать кнопку Try it Out!) - требуется только для тестов запросов
3. Внутри директории нужно создать и заполнить файл `input.json`, содержащий json с раздела [POST /system/docgenerator/prepareCatalog](https://delta.qa.loc/system/ActorApi?group=system#!/system__docgenerator/post_system_docgenerator_prepareCatalog) (для получения json нажать кнопку Try it Out!) - требуется только для тестов запросов и тестов API методов
Примечание: тесты можно запускать напрямую методами среды разработки либо из командной строки из нужной директории, например командой `go test -v -run <TestName>`, где `<TestName>` - название запускаемого теста.
Примечание 2: все тесты, кроме `TestGetAllPaths` при первом запуске генерируют фал `.log`. При каждом последующем запуске результаты вывода сравниваются с файлом и в случае, если они одинаковы, то в консоль будет выведено `All lines match the log file.`. В противном случае будут выведены различающиеся строки.
## Тесты Raw методов (Get, List)
@ -90,7 +94,7 @@ FAIL
## Тесты API методов
Запустить тест `TestGetAllPaths` в `decort-sdk/tests/platform_upgrade/cloud_test.go`
При наличии подсвеченных ошибок, проверить, что указанные методы API не являются устаревшими (deprecated). В противном случе добавить устаревшие методы в переменную `DEPRECATED_GROUPS` по адресу `decort-sdk/tests/platform_upgrade/utils_url.go`.
При наличии подсвеченных ошибок, проверить, что указанные методы API не являются устаревшими (deprecated). В противном случае добавить устаревшие методы в переменную `DEPRECATED_GROUPS` по адресу `decort-sdk/tests/platform_upgrade/utils_url.go`.
Пример вывода:
```go

@ -50,13 +50,16 @@ func TestGetListCloudAPI(t *testing.T) {
t.Fatalf("Cannot get client: %v", err)
}
const logFileName = "test_get_list_cloudAPI.log"
var testLogs []string
// Account
// List
bytes, err = client.CloudAPI().Account().ListRaw(context.Background(), account.ListRequest{})
if err != nil {
t.Error(err)
}
getResult("Account list", bytes, account.ListAccounts{}, t)
testLogs = append(testLogs, getResult("Account list", bytes, account.ListAccounts{}, t))
// Get
listAcc, _ := client.CloudAPI().Account().List(context.Background(), account.ListRequest{})
if len(listAcc.Data) > 0 {
@ -65,7 +68,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Account get", bytes, account.RecordAccount{}, t)
testLogs = append(testLogs, getResult("Account get", bytes, account.RecordAccount{}, t))
} else {
t.Errorf("Can not test Account get because account list is empty")
}
@ -76,7 +79,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Bservice list", bytes, bservice.ListBasicServices{}, t)
testLogs = append(testLogs, getResult("Bservice list", bytes, bservice.ListBasicServices{}, t))
// Get
listBServ, _ := client.CloudAPI().BService().List(context.Background(), bservice.ListRequest{})
if len(listBServ.Data) > 0 {
@ -85,7 +88,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Bservice get", bytes, bservice.RecordBasicService{}, t)
testLogs = append(testLogs, getResult("Bservice get", bytes, bservice.RecordBasicService{}, t))
} else {
t.Errorf("Can not test Bservice get because bservice list is empty")
}
@ -96,7 +99,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Compute list", bytes, compute.ListComputes{}, t)
testLogs = append(testLogs, getResult("Compute list", bytes, compute.ListComputes{}, t))
// Get
listComp, _ := client.CloudAPI().Compute().List(context.Background(), compute.ListRequest{})
if len(listComp.Data) > 0 {
@ -105,7 +108,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Compute get", bytes, compute.RecordCompute{}, t)
testLogs = append(testLogs, getResult("Compute get", bytes, compute.RecordCompute{}, t))
} else {
t.Errorf("Can not test Compute get because compute list is empty")
}
@ -116,7 +119,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Disk list", bytes, disks.ListDisks{}, t)
testLogs = append(testLogs, getResult("Disk list", bytes, disks.ListDisks{}, t))
// Get
listDisk, _ := client.CloudAPI().Disks().List(context.Background(), disks.ListRequest{})
if len(listDisk.Data) > 0 {
@ -125,7 +128,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Disk get", bytes, disks.RecordDisk{}, t)
testLogs = append(testLogs, getResult("Disk get", bytes, disks.RecordDisk{}, t))
} else {
t.Errorf("Can not test Disk get because disk list is empty")
}
@ -136,7 +139,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("ExtNet list", bytes, extnet.ListExtNets{}, t)
testLogs = append(testLogs, getResult("ExtNet list", bytes, extnet.ListExtNets{}, t))
// Get
listExtNet, _ := client.CloudAPI().ExtNet().List(context.Background(), extnet.ListRequest{})
if len(listExtNet.Data) > 0 {
@ -145,7 +148,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("ExtNet get", bytes, extnet.RecordExtNet{}, t)
testLogs = append(testLogs, getResult("ExtNet get", bytes, extnet.RecordExtNet{}, t))
} else {
t.Errorf("Can not test ExtNet get because listExtNet list is empty")
}
@ -156,7 +159,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("FLIPGroup list", bytes, flipgroup.ListFLIPGroups{}, t)
testLogs = append(testLogs, getResult("FLIPGroup list", bytes, flipgroup.ListFLIPGroups{}, t))
// Get
listFG, _ := client.CloudAPI().FLIPGroup().List(context.Background(), flipgroup.ListRequest{})
if len(listFG.Data) > 0 {
@ -165,7 +168,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("FLIPGroup get", bytes, flipgroup.RecordFLIPGroup{}, t)
testLogs = append(testLogs, getResult("FLIPGroup get", bytes, flipgroup.RecordFLIPGroup{}, t))
} else {
t.Errorf("Can not test FLIPGroup get because flipgroup list is empty")
}
@ -176,7 +179,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Image list", bytes, image.ListImages{}, t)
testLogs = append(testLogs, getResult("Image list", bytes, image.ListImages{}, t))
// Get
listImg, _ := client.CloudAPI().Image().List(context.Background(), image.ListRequest{})
if len(listImg.Data) > 0 {
@ -185,7 +188,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Image get", bytes, image.RecordImage{}, t)
testLogs = append(testLogs, getResult("Image get", bytes, image.RecordImage{}, t))
} else {
t.Errorf("Can not test Image get because Image list is empty")
}
@ -196,7 +199,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8CI list", bytes, k8ci.ListK8CI{}, t)
testLogs = append(testLogs, getResult("K8CI list", bytes, k8ci.ListK8CI{}, t))
// Get
listk8ci, _ := client.CloudAPI().K8CI().List(context.Background(), k8ci.ListRequest{})
if len(listk8ci.Data) > 0 {
@ -205,7 +208,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8CI get", bytes, k8ci.RecordK8CI{}, t)
testLogs = append(testLogs, getResult("K8CI get", bytes, k8ci.RecordK8CI{}, t))
} else {
t.Errorf("Can not test K8CI get because K8CI list is empty")
}
@ -216,7 +219,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8S list", bytes, k8s.ListK8SClusters{}, t)
testLogs = append(testLogs, getResult("K8S list", bytes, k8s.ListK8SClusters{}, t))
// Get
listk8s, _ := client.CloudAPI().K8S().List(context.Background(), k8s.ListRequest{})
if len(listk8s.Data) > 0 {
@ -225,7 +228,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8S get", bytes, k8s.RecordK8S{}, t)
testLogs = append(testLogs, getResult("K8S get", bytes, k8s.RecordK8S{}, t))
} else {
t.Errorf("Can not test K8S get because K8S list is empty")
}
@ -236,7 +239,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("LB list", bytes, lb.ListLB{}, t)
testLogs = append(testLogs, getResult("LB list", bytes, lb.ListLB{}, t))
// Get
listLB, _ := client.CloudAPI().LB().List(context.Background(), lb.ListRequest{})
if len(listLB.Data) > 0 {
@ -245,7 +248,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("LB get", bytes, lb.RecordLB{}, t)
testLogs = append(testLogs, getResult("LB get", bytes, lb.RecordLB{}, t))
} else {
t.Errorf("Can not test LB get because LB list is empty")
}
@ -256,7 +259,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Locations list", bytes, locations.ListLocations{}, t)
testLogs = append(testLogs, getResult("Locations list", bytes, locations.ListLocations{}, t))
// RG
// List
@ -264,7 +267,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("RG list", bytes, rg.ListResourceGroups{}, t)
testLogs = append(testLogs, getResult("RG list", bytes, rg.ListResourceGroups{}, t))
// Get
listRG, _ := client.CloudAPI().RG().List(context.Background(), rg.ListRequest{})
if len(listRG.Data) > 0 {
@ -273,7 +276,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("RG get", bytes, rg.RecordResourceGroup{}, t)
testLogs = append(testLogs, getResult("RG get", bytes, rg.RecordResourceGroup{}, t))
} else {
t.Errorf("Can not test RG get because RG list is empty")
}
@ -284,7 +287,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Sizes list", bytes, sizes.ListSizes{}, t)
testLogs = append(testLogs, getResult("Sizes list", bytes, sizes.ListSizes{}, t))
// Stack
// List
@ -292,7 +295,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Stack list", bytes, stack.ListStacks{}, t)
testLogs = append(testLogs, getResult("Stack list", bytes, stack.ListStacks{}, t))
// Tasks
// List
@ -300,7 +303,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Tasks list", bytes, tasks.ListTasks{}, t)
testLogs = append(testLogs, getResult("Tasks list", bytes, tasks.ListTasks{}, t))
// Get
listTasks, _ := client.CloudAPI().Tasks().List(context.Background(), tasks.ListRequest{})
if len(listTasks.Data) > 0 {
@ -309,7 +312,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Tasks get", bytes, tasks.RecordAsyncTask{}, t)
testLogs = append(testLogs, getResult("Tasks get", bytes, tasks.RecordAsyncTask{}, t))
} else {
t.Errorf("Can not test Tasks get because Tasks list is empty")
}
@ -320,7 +323,7 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("VINS list", bytes, vins.ListVINS{}, t)
testLogs = append(testLogs, getResult("VINS list", bytes, vins.ListVINS{}, t))
// Get
listVINS, _ := client.CloudAPI().VINS().List(context.Background(), vins.ListRequest{})
if len(listVINS.Data) > 0 {
@ -329,10 +332,12 @@ func TestGetListCloudAPI(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("VINS get", bytes, vins.RecordVINS{}, t)
testLogs = append(testLogs, getResult("VINS get", bytes, vins.RecordVINS{}, t))
} else {
t.Errorf("Can not test VINS get because VINS list is empty")
}
compareLogs(logFileName, testLogs, t, "get")
}
// WARNING: not working correctly due to inclusions of tagless structures in cloudbroker
@ -345,13 +350,15 @@ func TestGetListCloudbroker(t *testing.T) {
t.Fatalf("Cannot get client: %v", err)
}
const logFileName = "test_get_list_cloudbroker.log"
var testLogs = make([]string, 0)
// Account
// List
bytes, err = client.CloudBroker().Account().ListRaw(context.Background(), account_cb.ListRequest{})
if err != nil {
t.Error(err)
}
getResult("Account list", bytes, account_cb.ListAccounts{}, t)
testLogs = append(testLogs, getResult("Account list", bytes, account_cb.ListAccounts{}, t))
// Get
listAcc, _ := client.CloudBroker().Account().List(context.Background(), account_cb.ListRequest{})
if len(listAcc.Data) > 0 {
@ -360,7 +367,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Account get", bytes, account_cb.RecordAccount{}, t)
testLogs = append(testLogs, getResult("Account get", bytes, account_cb.RecordAccount{}, t))
} else {
t.Errorf("Can not test Account get because account list is empty")
}
@ -371,7 +378,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Audit list", bytes, audit_cb.ListAudits{}, t)
testLogs = append(testLogs, getResult("Audit list", bytes, audit_cb.ListAudits{}, t))
// Get
listAudits, _ := client.CloudBroker().Audit().List(context.Background(), audit_cb.ListRequest{})
if len(listAudits.Data) > 0 {
@ -380,7 +387,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Audit get", bytes, audit_cb.RecordAudit{}, t)
testLogs = append(testLogs, getResult("Audit get", bytes, audit_cb.RecordAudit{}, t))
} else {
t.Errorf("Can not test Audit get because Audit list is empty")
}
@ -391,7 +398,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Compute list", bytes, compute_cb.ListComputes{}, t)
testLogs = append(testLogs, getResult("Compute list", bytes, compute_cb.ListComputes{}, t))
// Get
listComp, _ := client.CloudBroker().Compute().List(context.Background(), compute_cb.ListRequest{})
if len(listComp.Data) > 0 {
@ -400,7 +407,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Compute get", bytes, compute_cb.RecordCompute{}, t)
testLogs = append(testLogs, getResult("Compute get", bytes, compute_cb.RecordCompute{}, t))
} else {
t.Errorf("Can not test Compute get because compute list is empty")
}
@ -411,7 +418,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Disk list", bytes, disks_cb.ListDisks{}, t)
testLogs = append(testLogs, getResult("Disk list", bytes, disks_cb.ListDisks{}, t))
// Get
listDisk, _ := client.CloudBroker().Disks().List(context.Background(), disks_cb.ListRequest{})
if len(listDisk.Data) > 0 {
@ -420,7 +427,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Disk get", bytes, disks_cb.RecordDisk{}, t)
testLogs = append(testLogs, getResult("Disk get", bytes, disks_cb.RecordDisk{}, t))
} else {
t.Errorf("Can not test Disk get because disk list is empty")
}
@ -431,7 +438,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("ExtNet list", bytes, extnet_cb.ListExtNet{}, t)
testLogs = append(testLogs, getResult("ExtNet list", bytes, extnet_cb.ListExtNet{}, t))
// Get
listExtNet, _ := client.CloudBroker().ExtNet().List(context.Background(), extnet_cb.ListRequest{})
if len(listExtNet.Data) > 0 {
@ -440,7 +447,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("ExtNet get", bytes, extnet_cb.RecordExtNet{}, t)
testLogs = append(testLogs, getResult("ExtNet get", bytes, extnet_cb.RecordExtNet{}, t))
} else {
t.Errorf("Can not test ExtNet get because listExtNet list is empty")
}
@ -451,7 +458,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("FLIPGroup list", bytes, flipgroup_cb.ListFLIPGroups{}, t)
testLogs = append(testLogs, getResult("FLIPGroup list", bytes, flipgroup_cb.ListFLIPGroups{}, t))
// Get
listFG, _ := client.CloudBroker().FLIPGroup().List(context.Background(), flipgroup_cb.ListRequest{})
if len(listFG.Data) > 0 {
@ -460,7 +467,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("FLIPGroup get", bytes, flipgroup_cb.RecordFLIPGroup{}, t)
testLogs = append(testLogs, getResult("FLIPGroup get", bytes, flipgroup_cb.RecordFLIPGroup{}, t))
} else {
t.Errorf("Can not test FLIPGroup get because flipgroup list is empty")
}
@ -471,7 +478,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Grid list", bytes, grid_cb.ListGrids{}, t)
testLogs = append(testLogs, getResult("Grid list", bytes, grid_cb.ListGrids{}, t))
// Get
listGrid, _ := client.CloudBroker().Grid().List(context.Background(), grid_cb.ListRequest{})
if len(listGrid.Data) > 0 {
@ -480,7 +487,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Grid get", bytes, grid_cb.RecordGrid{}, t)
testLogs = append(testLogs, getResult("Grid get", bytes, grid_cb.RecordGrid{}, t))
} else {
t.Errorf("Can not test Grid get because Grid list is empty")
}
@ -491,7 +498,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Image list", bytes, image_cb.ListImages{}, t)
testLogs = append(testLogs, getResult("Image list", bytes, image_cb.ListImages{}, t))
// Get
listImg, _ := client.CloudBroker().Image().List(context.Background(), image_cb.ListRequest{})
if len(listImg.Data) > 0 {
@ -500,7 +507,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Image get", bytes, image_cb.RecordImage{}, t)
testLogs = append(testLogs, getResult("Image get", bytes, image_cb.RecordImage{}, t))
} else {
t.Errorf("Can not test Image get because Image list is empty")
}
@ -511,7 +518,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8CI list", bytes, k8ci_cb.ListK8CI{}, t)
testLogs = append(testLogs, getResult("K8CI list", bytes, k8ci_cb.ListK8CI{}, t))
// Get
listk8ci, _ := client.CloudBroker().K8CI().List(context.Background(), k8ci_cb.ListRequest{})
if len(listk8ci.Data) > 0 {
@ -520,7 +527,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8CI get", bytes, k8ci_cb.RecordK8CI{}, t)
testLogs = append(testLogs, getResult("K8CI get", bytes, k8ci_cb.RecordK8CI{}, t))
} else {
t.Errorf("Can not test K8CI get because K8CI list is empty")
}
@ -531,7 +538,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8S list", bytes, k8s_cb.ListK8S{}, t)
testLogs = append(testLogs, getResult("K8S list", bytes, k8s_cb.ListK8S{}, t))
// Get
listk8s, _ := client.CloudBroker().K8S().List(context.Background(), k8s_cb.ListRequest{})
if len(listk8s.Data) > 0 {
@ -540,7 +547,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("K8S get", bytes, k8s_cb.RecordK8S{}, t)
testLogs = append(testLogs, getResult("K8S get", bytes, k8s_cb.RecordK8S{}, t))
} else {
t.Errorf("Can not test K8S get because K8S list is empty")
}
@ -551,7 +558,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("LB list", bytes, lb_cb.ListLB{}, t)
testLogs = append(testLogs, getResult("LB list", bytes, lb_cb.ListLB{}, t))
// Get
listLB, _ := client.CloudBroker().LB().List(context.Background(), lb_cb.ListRequest{})
if len(listLB.Data) > 0 {
@ -560,7 +567,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("LB get", bytes, lb_cb.RecordLB{}, t)
testLogs = append(testLogs, getResult("LB get", bytes, lb_cb.RecordLB{}, t))
} else {
t.Errorf("Can not test LB get because LB list is empty")
}
@ -571,7 +578,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Pcidevice list", bytes, pcidevice_cb.ListPCIDevices{}, t)
testLogs = append(testLogs, getResult("Pcidevice list", bytes, pcidevice_cb.ListPCIDevices{}, t))
// RG
// List
@ -579,7 +586,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("RG list", bytes, rg_cb.ListRG{}, t)
testLogs = append(testLogs, getResult("RG list", bytes, rg_cb.ListRG{}, t))
// Get
listRG, _ := client.CloudBroker().RG().List(context.Background(), rg_cb.ListRequest{})
if len(listRG.Data) > 0 {
@ -588,7 +595,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("RG get", bytes, rg_cb.RecordRG{}, t)
testLogs = append(testLogs, getResult("RG get", bytes, rg_cb.RecordRG{}, t))
} else {
t.Errorf("Can not test RG get because RG list is empty")
}
@ -599,7 +606,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("SEP list", bytes, sep_cb.ListSEP{}, t)
testLogs = append(testLogs, getResult("SEP list", bytes, sep_cb.ListSEP{}, t))
// Get
listSEP, _ := client.CloudBroker().SEP().List(context.Background(), sep_cb.ListRequest{})
if len(listSEP.Data) > 0 {
@ -608,7 +615,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("SEP get", bytes, sep_cb.RecordSEP{}, t)
testLogs = append(testLogs, getResult("SEP get", bytes, sep_cb.RecordSEP{}, t))
} else {
t.Errorf("Can not test SEP get because SEP list is empty")
}
@ -619,7 +626,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Stack list", bytes, stack_cb.ListStacks{}, t)
testLogs = append(testLogs, getResult("Stack list", bytes, stack_cb.ListStacks{}, t))
// Get
listStack, _ := client.CloudBroker().Stack().List(context.Background(), stack_cb.ListRequest{})
if len(listStack.Data) > 0 {
@ -628,7 +635,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Stack get", bytes, stack_cb.InfoStack{}, t)
testLogs = append(testLogs, getResult("Stack get", bytes, stack_cb.InfoStack{}, t))
} else {
t.Errorf("Can not test Stack get because Stack list is empty")
}
@ -639,7 +646,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("Tasks list", bytes, tasks_cb.ListTasks{}, t)
testLogs = append(testLogs, getResult("Tasks list", bytes, tasks_cb.ListTasks{}, t))
// VINS
// List
@ -647,7 +654,7 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("VINS list", bytes, vins_cb.ListVINS{}, t)
testLogs = append(testLogs, getResult("VINS list", bytes, vins_cb.ListVINS{}, t))
// Get
listVINS, _ := client.CloudBroker().VINS().List(context.Background(), vins_cb.ListRequest{})
if len(listVINS.Data) > 0 {
@ -656,10 +663,11 @@ func TestGetListCloudbroker(t *testing.T) {
if err != nil {
t.Error(err)
}
getResult("VINS get", bytes, vins_cb.RecordVINS{}, t)
testLogs = append(testLogs, getResult("VINS get", bytes, vins_cb.RecordVINS{}, t))
} else {
t.Errorf("Can not test VINS get because VINS list is empty")
}
compareLogs(logFileName, testLogs, t, "get")
}
// TestRequestsCloudAPI tests platform requests vs. golang request structures in sdk for cloudapi requests

@ -557,6 +557,7 @@ func getRequestsMapCloudbroker() map[string]interface{} {
"/cloudbroker/disks/create": disks_cb.CreateRequest{},
"/cloudbroker/disks/delete": disks_cb.DeleteRequest{},
"/cloudbroker/disks/deleteDisks": disks_cb.DeleteDisksRequest{},
"/cloudbroker/disks/depresent": disks_cb.DepresentRequest{},
"/cloudbroker/disks/fromPlatformDisk": disks_cb.FromPlatformDiskRequest{},
"/cloudbroker/disks/get": disks_cb.GetRequest{},
"/cloudbroker/disks/limitIO": disks_cb.LimitIORequest{},
@ -565,6 +566,7 @@ func getRequestsMapCloudbroker() map[string]interface{} {
"/cloudbroker/disks/listTypes": disks_cb.ListTypesRequest{},
"/cloudbroker/disks/listUnattached": disks_cb.ListUnattachedRequest{},
"/cloudbroker/disks/rename": disks_cb.RenameRequest{},
"/cloudbroker/disks/present": disks_cb.PresentRequest{},
"/cloudbroker/disks/replicate": disks_cb.ReplicateRequest{},
"/cloudbroker/disks/replicationResume": disks_cb.ReplicationResumeRequest{},
"/cloudbroker/disks/replicationReverse": disks_cb.ReplicationReverseRequest{},

@ -0,0 +1,31 @@
[
"Account list: OK",
"Account get: OK",
"",
"Bservice get: OK",
"Compute list: \nPlatform has these fields that golang struct doesn't: [lb mgmt_target mgmt_mac mgmt_slot]\n",
"Compute get: \nPlatform has these fields that golang struct doesn't: [mgmt_target mgmt_mac mgmt_slot lb]\n",
"Disk list: OK",
"Disk get: OK",
"",
"ExtNet get: OK",
"FLIPGroup list: OK",
"",
"",
"Image get: \nPlatform has these fields that golang struct doesn't: [12]\n",
"K8CI list: OK",
"",
"K8S list: OK",
"K8S get: OK",
"LB list: \nPlatform has these fields that golang struct doesn't: [fs.inotify.max_queued_events kernel.kptr_restrict net.ipv4.tcp_congestion_control]\n",
"LB get: \nPlatform has these fields that golang struct doesn't: [kernel.kptr_restrict net.ipv4.tcp_congestion_control fs.inotify.max_queued_events]\n",
"Locations list: OK",
"RG list: OK",
"",
"Sizes list: OK",
"",
"Tasks list: \nPlatform has these fields that golang struct doesn't: [completed guid stage updateTime updatedTime auditId error log status]\n",
"Tasks get: \nPlatform has these fields that golang struct doesn't: [updatedTime completed error updateTime auditId stage status log]\n",
"",
"VINS get: OK"
]

@ -0,0 +1,34 @@
[
"Account list: OK",
"Account get: OK",
"",
"Audit get: OK",
"Compute list: \nPlatform has these fields that golang struct doesn't: [disks]\n",
"Compute get: OK",
"Disk list: \nPlatform has these fields that golang struct doesn't: [machineId machineName sepType devicename]\n",
"Disk get: \nPlatform has these fields that golang struct doesn't: [devicename sepType updatedBy]\n",
"ExtNet list: OK",
"ExtNet get: OK",
"FLIPGroup list: OK",
"",
"Grid list: \nPlatform has these fields that golang struct doesn't: [1 90 380 1 90 380]\n",
"Grid get: OK",
"Image list: OK",
"Image get: OK",
"K8CI list: \nPlatform has these fields that golang struct doesn't: [createdTime]\n",
"K8CI get: OK",
"K8S list: OK",
"K8S get: OK",
"LB list: OK",
"LB get: OK",
"Pcidevice list: OK",
"RG list: OK",
"RG get: OK",
"SEP list: \nPlatform has these fields that golang struct doesn't: [protocol disk_max_size format name name_prefix pools]\n",
"SEP get: \nPlatform has these fields that golang struct doesn't: [format name name_prefix pools protocol disk_max_size]\n",
"Stack list: OK",
"Stack get: OK",
"Tasks list: \nPlatform has these fields that golang struct doesn't: [stage status error log auditId completed updateTime guid]\n",
"",
"VINS get: \nPlatform has these fields that golang struct doesn't: [computes config config config]\n"
]

@ -0,0 +1,14 @@
[
"Path /cloudapi/compute/antiAffinityRuleAdd has following errors: [Field value has different required parameters on the platform and in golang structure]",
"Path /cloudapi/user/setData has following errors: [Field data has different required parameters on the platform and in golang structure]",
"Path /cloudapi/compute/affinityRuleRemove has following errors: [Field value has different required parameters on the platform and in golang structure]",
"Path /cloudapi/compute/createTemplate has following errors: [Platform (3) and golang structure (2) have different amount of fields. Platform has field asyncMode that golang structure doesn't]",
"Path /cloudapi/k8s/create has following errors: [Field oidcCertificate has different type parameters on the platform and in golang structure]",
"Path /cloudapi/disks/fromPlatformDisk has following errors: [Platform (14) and golang structure (13) have different amount of fields. Field drivers has different type parameters on the platform and in golang structure Platform has field asyncMode that golang structure doesn't]",
"Path /cloudapi/compute/affinityRuleAdd has following errors: [Field value has different required parameters on the platform and in golang structure]",
"Path /cloudapi/compute/antiAffinityRuleRemove has following errors: [Field value has different required parameters on the platform and in golang structure]",
"Path /cloudapi/compute/createTemplateFromBlank has following errors: [Platform (11) and golang structure (10) have different amount of fields. Platform has field asyncMode that golang structure doesn't]",
"Path /cloudapi/lb/create has following errors: [Field extnetId has different required parameters on the platform and in golang structure Field vinsId has different required parameters on the platform and in golang structure]",
"Path /cloudapi/image/list has following errors: [Field size has different type parameters on the platform and in golang structure]",
"Path /cloudapi/compute/snapshotDelete has following errors: [Platform (3) and golang structure (2) have different amount of fields. Platform has field asyncMode that golang structure doesn't]"
]

@ -0,0 +1 @@
["Path /cloudbroker/compute/createTemplate has following errors: [Platform (4) and golang structure (3) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/backup/createDisksBackup has following errors: [Platform (3) and golang structure (2) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/compute/affinityRuleAdd has following errors: [Field value has different required parameters on the platform and in golang structure]","Path /cloudbroker/apiaccess/update has following errors: [Platform has field apis that golang structure doesn't]","Path /cloudbroker/compute/antiAffinityRuleRemove has following errors: [Field value has different required parameters on the platform and in golang structure]","Path /cloudbroker/compute/snapshotDelete has following errors: [Platform (3) and golang structure (2) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/backup/restoreDiskFromBackup has following errors: [Platform (5) and golang structure (4) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/backup/createDiskBackup has following errors: [Platform (4) and golang structure (3) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/compute/createTemplateFromBlank has following errors: [Platform (11) and golang structure (10) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/account/setCpuAllocationRatio has following errors: [Field ratio has different required parameters on the platform and in golang structure]","Path /cloudbroker/disks/fromPlatformDisk has following errors: [Platform (14) and golang structure (13) have different amount of fields. Field drivers has different type parameters on the platform and in golang structure Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/lb/create has following errors: [Field extnetId has different required parameters on the platform and in golang structure Field vinsId has different required parameters on the platform and in golang structure]","Path /cloudbroker/stack/setCpuAllocationRatio has following errors: [Field ratio has different required parameters on the platform and in golang structure]","Path /cloudbroker/backup/deleteDiskBackup has following errors: [Platform (3) and golang structure (2) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/image/updateNodes has following errors: [Field enabledStacks has different type parameters on the platform and in golang structure]","Path /cloudbroker/stack/setMemAllocationRatio has following errors: [Field ratio has different required parameters on the platform and in golang structure]","Path /cloudbroker/compute/antiAffinityRuleAdd has following errors: [Field value has different required parameters on the platform and in golang structure]","Path /cloudbroker/k8s/create has following errors: [Field oidcCertificate has different type parameters on the platform and in golang structure]","Path /cloudbroker/backup/restoreDisksFromBackup has following errors: [Platform (3) and golang structure (2) have different amount of fields. Platform has field disks that golang structure doesn't Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/node/enable has following errors: [Platform (4) and golang structure (3) have different amount of fields. Platform has field asyncMode that golang structure doesn't]","Path /cloudbroker/compute/affinityRuleRemove has following errors: [Field value has different required parameters on the platform and in golang structure]","Path /cloudbroker/image/list has following errors: [Field size has different type parameters on the platform and in golang structure]"]

@ -56,7 +56,7 @@ func getClient() (*decort.DecortClient, error) {
}
// getResult checks how json-structure of bytes is different from golang structure and return t.Error if there are any differences.
func getResult(testName string, bytes []byte, structure any, t *testing.T) {
func getResult(testName string, bytes []byte, structure any, t *testing.T) string {
// convert bytes to map[string]interface{}
bytesMap, err := GetMapFromBytes(bytes)
if err != nil {
@ -68,8 +68,11 @@ func getResult(testName string, bytes []byte, structure any, t *testing.T) {
// assert if they are equal
if !reflect.DeepEqual(bytesMap, structMap) {
t.Errorf(getDifference(testName, bytesMap, structMap))
var result = getDifference(testName, bytesMap, structMap)
t.Errorf(result)
return result
}
return ""
}
// getDifference tells which fields are present in bytesMap and not present in structMap and vice versa.

@ -0,0 +1,119 @@
package test
import (
"bufio"
"encoding/json"
"io"
"os"
"regexp"
"sort"
"strings"
"testing"
)
func compareLogs(logFileName string, logsData []string, t *testing.T, testType string) {
if _, err := os.Stat(logFileName); os.IsNotExist(err) {
file, err := os.Create(logFileName)
if err != nil {
t.Errorf("Failed to create log file: %v", err)
}
defer file.Close()
writer := bufio.NewWriter(file)
jsonData, err := json.MarshalIndent(logsData, "", " ")
if err != nil {
t.Errorf("Failed to marshal logsData to JSON: %v", err)
}
_, err = writer.WriteString(string(jsonData))
if err != nil {
t.Errorf("Failed to write JSON to log file: %v", err)
}
writer.Flush()
} else {
file, err := os.Open(logFileName)
if err != nil {
t.Errorf("Failed to open log file: %v", err)
}
defer file.Close()
reader := bufio.NewReader(file)
var sb strings.Builder
for {
line, err := reader.ReadString('\n')
if err != nil {
if err == io.EOF {
sb.WriteString(strings.TrimSpace(line))
break
}
t.Errorf("Error reading log file: %v", err)
return
}
sb.WriteString(strings.TrimSpace(line))
}
var fileContent = sb.String()
var fileLogsData []string
err = json.Unmarshal([]byte(fileContent), &fileLogsData)
if err != nil {
t.Errorf("Failed to unmarshal JSON from log file: %v", err)
}
if len(fileLogsData) != len(logsData) {
t.Errorf("Log data length does not match. Got: %d, Expected: %d", len(fileLogsData), len(logsData))
}
var allLinesMatch = true
switch testType {
default:
for i := range logsData {
if sortBracketsContent(fileLogsData[i]) != sortBracketsContent(logsData[i]) {
allLinesMatch = false
t.Errorf("Line %d does not match. Got: %s, Expected: %s", i+1, sortBracketsContent(fileLogsData[i]), sortBracketsContent(logsData[i]))
}
}
if allLinesMatch {
t.Log("\nAll lines match the log file.")
}
case "request":
var tmp = make(map[string]struct{})
for _, v := range fileLogsData {
if _, ok := tmp[v]; ok {
delete(tmp, v)
} else {
tmp[v] = struct{}{}
}
}
for _, v := range logsData {
if _, ok := tmp[v]; ok {
delete(tmp, v)
} else {
tmp[v] = struct{}{}
}
}
if len(tmp) == 0 {
t.Log("\nAll lines match the log file.")
return
}
for i := range tmp {
t.Errorf("Line %s does not match.", i)
}
}
}
}
func sortBracketsContent(log string) string {
re := regexp.MustCompile(`\[([^\[\]]*)\]`)
return re.ReplaceAllStringFunc(log, func(match string) string {
content := match[1 : len(match)-1]
parts := strings.Split(content, " ")
sort.Strings(parts)
return "[" + strings.Join(parts, " ") + "]"
})
}

@ -51,16 +51,21 @@ func getBytesFromJSON(fileName string, t *testing.T) []byte {
func getErrorsFromJSON(bytes []byte, t *testing.T, cloud string) {
var requests map[string]interface{}
var logFileName string
switch cloud {
case "cloudapi":
requests = getRequestsMapCloudAPI()
logFileName = "test_requests_cloudAPI.log"
case "cloudbroker":
requests = getRequestsMapCloudbroker()
logFileName = "test_requests_cloudbroker.log"
default:
t.Fatalf("Wrong cloud provided, expected `cloudapi` or `cloudbroker`, got %s", cloud)
}
var dataLogs []string
paths, err := getMapFromFile(bytes)
if err != nil {
t.Error(err)
@ -131,14 +136,19 @@ func getErrorsFromJSON(bytes []byte, t *testing.T, cloud string) {
}
}
if len(errs) > 0 {
t.Errorf("Path %s has following errors: %v", k, errs)
msg := fmt.Sprintf("Path %s has following errors: %v", k, errs)
t.Error(msg)
dataLogs = append(dataLogs, msg)
}
}
if len(requests) != i {
t.Errorf("Amount of structure checked (%d) is not the same as amount of platform requests available (%d), please check getRequestsMapCloudAPI func in code.",
msg := fmt.Sprintf("Amount of structure checked (%d) is not the same as amount of platform requests available (%d), please check getRequestsMapCloudAPI func in code.",
i, len(requests))
t.Error(msg)
dataLogs = append(dataLogs, msg)
}
compareLogs(logFileName, dataLogs, t, "request")
}
// checkName checks if name field from platform has the same value as json tag in golang structure (maybe including omitempty)
@ -211,8 +221,13 @@ func checkKind(platformType, items string, typ reflect.Type) bool {
return true
}
return false
}
default: // for cases like dataDisks etc.
return true
}
return false
default: // for cases like drivers etc
return true
}
}

Loading…
Cancel
Save