Compare commits

...

1 Commits

Author SHA1 Message Date
bb90a2d511 v1.13.3 2025-12-29 14:16:28 +03:00
10 changed files with 99 additions and 64 deletions

View File

@@ -1,4 +1,4 @@
## Version 1.13.2 ## Version 1.13.3
Методы `Audits` в cloudapi/compute, cloudbroker/compute, cloudapi/account, cloudbroker/account, cloudapi/vins, cloudbroker/vins, cloudapi/rg и cloudbroker/rg стали deprecated и в следующих версиях будут удалены, вместо них необходимо использовать метод `List` в cloudapi/audit и cloudbroker/audit с соответствующими фильтрами Методы `Audits` в cloudapi/compute, cloudbroker/compute, cloudapi/account, cloudbroker/account, cloudapi/vins, cloudbroker/vins, cloudapi/rg и cloudbroker/rg стали deprecated и в следующих версиях будут удалены, вместо них необходимо использовать метод `List` в cloudapi/audit и cloudbroker/audit с соответствующими фильтрами
Метод `ListNodes` в cloudbroker/image стал deprecated и в следующих версиях будет удалён Метод `ListNodes` в cloudbroker/image стал deprecated и в следующих версиях будет удалён
@@ -9,49 +9,38 @@
### Добавлено ### Добавлено
#### audit
| Идентификатор<br>задачи | Описание |
| --- | ---|
| BGOS-706 | Поля `ResgroupID`, `AccountID`, `ComputeID` в структуру ответа `RecordAudit` в cloudbroker/audit |
#### compute #### compute
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-703 | Опциональное поле `NetMask` в структуру запроса `NetAttachRequest` в cloudbroker/compute | | BGOS-713 | Опциональное поле `NetMap` в структуру запроса `StartMigrationOutRequest` в cloudbroker/compute |
| BGOS-704 | Поле `SepID` в структуру ответа `InfoDisk` в cloudapi/compute и cloudbroker/compute |
#### kvmx86
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-703 | Опциональное поле `NetMask` в структуры запросов `Interface` в cloudapi/kvmx86 и cloudbroker/kvmx86 |
#### sep #### sep
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | ---| | --- | --- |
| BGOS-704 | Опциональное поле `SepIDs` в структуре запроса `ListRequest` в cloudbroker/sep | | BGOS-712 | Возвращаемый тип методов `AddConsumerNodes` и `AddProviderNodes` изменен с `bool` на `uint64` в cloudbroker/sep |
| BGOS-722 | Валидатор для поля `SEPType` в структуре запроса `CreateRequest` в cloudbroker/sep |
#### storage policy
| Идентификатор<br>задачи | Описание |
| --- | ---|
| BGOS-708 | Поле `SepTechStatus` в структуру запроса `ListRequest` в cloudapi/stpolicy и в cloudbroker/stpolicy |
| BGOS-710 | Обязательное поле `AccessSEPsPool` в структуру запроса `UpdateRequest` в cloudbroker/stpolicy |
#### trunk
| Идентификатор<br>задачи | Описание |
| --- | ---|
| BGOS-705 | Поле `MTU` в структуру ответа `ItemTrunk` в cloudapi/trunk и в cloudbroker/trunk |
| BGOS-705 | Опциональное поле `MTU` в структуры запроса`CreateRequest` и `UpdateRequest` в cloudbroker/trunk |
### Изменено ### Изменено
#### compute #### compute
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-707 | Поле `Value` стало обязательным в структурах запроса `AntiAffinityRuleAddRequest`, `AntiAffinityRuleRemoveRequest`, `AffinityRuleAddRequest` и `AffinityRuleRemoveRequest` в cloudapi/compute и в cloudbroker/compute | | BGOS-721 | Тип поля `StoragePolicyID` изменен с опционального на обязательный в структуре запроса `CloneRequest` cloudbroker/compute |
| BGOS-707 | Тип поля `StoragePolicyID` изменен с обязательного на опциональный в структуре запроса`CloneRequest` в cloudbroker/compute |
| BGOS-707 | Тип поля `ComputeID` с `uint64` на `string` в структуре запроса `GetCloneStatusRequest` в cloudbroker/compute |
#### node #### grid
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-709 | Поле `VFNum` заменено на поле `FNID` в структуре `VFParam` в структуре запроса `SetVFsParamsRequest` в cloudbroker/node | | BGOS-719 | Поле `Age` в структуре запроса `PurgeLogsRequest` стало необязательным в cloudbroker/grid |
#### storage policy
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-720 | Тип поля `AccessSEPsPools` изменен с обязательного на опциональный в структуре запроса `UpdateRequest` в cloudbroker/stpolicy |
### Удалено
#### sep
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-712 | Поля `ProviderNIDs` и `ConsumerNIDs` удалены из структуры запроса `CreateRequest` в cloudbroker/sep |

View File

@@ -66,7 +66,7 @@ var (
loaderTypeValues = []string{"linux", "windows", "unknown"} loaderTypeValues = []string{"linux", "windows", "unknown"}
sepTypeValues = []string{"hitachi", "dorado", "tatlin", "shared", "local", "des"} sepTypeValues = []string{"hitachi", "dorado", "tatlin", "shared", "local", "des", "ustor"}
languageValues = []string{"ru", "en"} languageValues = []string{"ru", "en"}

View File

@@ -19,8 +19,8 @@ type CloneRequest struct {
Name string `url:"name" json:"name" validate:"required"` Name string `url:"name" json:"name" validate:"required"`
// ID of the Storage Policy // ID of the Storage Policy
// Required: false // Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id"` StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Timestamp of the parent's snapshot to create clone from // Timestamp of the parent's snapshot to create clone from
// Required: false // Required: false

View File

@@ -33,7 +33,11 @@ type StartMigrationOutRequest struct {
// Mapping of guest disk target names to absolute paths on the destination host. // Mapping of guest disk target names to absolute paths on the destination host.
// Required: false // Required: false
Diskmap map[string]string `url:"diskmap,omitempty" json:"diskmap,omitempty"` DiskMap map[string]string `url:"diskmap,omitempty" json:"diskmap,omitempty"`
// Mapping of network interfaces
// Required: false
NetMap map[string]string `url:"netmap,omitempty" json:"netmap,omitempty"`
// Mapping for CD/DVD devices or their source paths to new ISO/device paths on the destination // Mapping for CD/DVD devices or their source paths to new ISO/device paths on the destination
// Required: false // Required: false

View File

@@ -15,8 +15,8 @@ type PurgeLogsRequest struct {
GID uint64 `url:"gid" json:"gid" validate:"required"` GID uint64 `url:"gid" json:"gid" validate:"required"`
// Age of the records to remove, e.g. -1h for records older than 1 hour, -1w - one week, etc // Age of the records to remove, e.g. -1h for records older than 1 hour, -1w - one week, etc
// Required: true // Required: false
Age string `url:"age" json:"age" validate:"required"` Age string `url:"age,omitempty" json:"age,omitempty"`
} }
// PurgeLogs clear Log and ECO records that are older than the specified age. // PurgeLogs clear Log and ECO records that are older than the specified age.

View File

@@ -20,22 +20,22 @@ type AddConsumerNodesRequest struct {
} }
// AddConsumerNodes adds consumer nodes to SEP parameters // AddConsumerNodes adds consumer nodes to SEP parameters
func (s SEP) AddConsumerNodes(ctx context.Context, req AddConsumerNodesRequest) (bool, error) { func (s SEP) AddConsumerNodes(ctx context.Context, req AddConsumerNodesRequest) (uint64, error) {
err := validators.ValidateRequest(req) err := validators.ValidateRequest(req)
if err != nil { if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err)) return 0, validators.ValidationErrors(validators.GetErrors(err))
} }
url := "/cloudbroker/sep/addConsumerNodes" url := "/cloudbroker/sep/addConsumerNodes"
res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return 0, err
} }
result, err := strconv.ParseBool(string(res)) result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil { if err != nil {
return false, err return 0, err
} }
return result, nil return result, nil

View File

@@ -20,22 +20,22 @@ type AddProviderNodesRequest struct {
} }
// AddProviderNodes adds provider nodes to SEP parameters // AddProviderNodes adds provider nodes to SEP parameters
func (s SEP) AddProviderNodes(ctx context.Context, req AddProviderNodesRequest) (bool, error) { func (s SEP) AddProviderNodes(ctx context.Context, req AddProviderNodesRequest) (uint64, error) {
err := validators.ValidateRequest(req) err := validators.ValidateRequest(req)
if err != nil { if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err)) return 0, validators.ValidationErrors(validators.GetErrors(err))
} }
url := "/cloudbroker/sep/addProviderNodes" url := "/cloudbroker/sep/addProviderNodes"
res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := s.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return 0, err
} }
result, err := strconv.ParseBool(string(res)) result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil { if err != nil {
return false, err return 0, err
} }
return result, nil return result, nil

View File

@@ -20,7 +20,7 @@ type CreateRequest struct {
// Type of storage // Type of storage
// Required: true // Required: true
SEPType string `url:"sep_type" json:"sep_type" validate:"required"` SEPType string `url:"sep_type" json:"sep_type" validate:"required,sepType"`
// SEP config // SEP config
// Required: true // Required: true
@@ -30,14 +30,6 @@ type CreateRequest struct {
// Required: false // Required: false
Description string `url:"description,omitempty" json:"description,omitempty"` Description string `url:"description,omitempty" json:"description,omitempty"`
// List of provider node IDs
// Required: false
ProviderNIDs []uint64 `url:"provider_nids,omitempty" json:"provider_nids,omitempty"`
// List of consumer node IDs
// Required: false
ConsumerNIDs []uint64 `url:"consumer_nids,omitempty" json:"consumer_nids,omitempty"`
// Enable SEP after creation // Enable SEP after creation
// Required: false // Required: false
Enable bool `url:"enable,omitempty" json:"enable,omitempty"` Enable bool `url:"enable,omitempty" json:"enable,omitempty"`

View File

@@ -15,8 +15,8 @@ type UpdateRequest struct {
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"` StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// List of storage endpoint access objects // List of storage endpoint access objects
// Required: true // Required: false
AccessSEPsPools []AccessSEPsPool `url:"access_seps_pools" json:"access_seps_pools" validate:"required"` AccessSEPsPools []AccessSEPsPool `url:"access_seps_pools,omitempty" json:"access_seps_pools,omitempty"`
// New name for the storage policy // New name for the storage policy
// Required: false // Required: false

View File

@@ -9,6 +9,31 @@ import (
"testing" "testing"
) )
// extractTypeFromSchema extracts type from schema, handling oneOf cases
// When oneOf contains a type and null, it returns the non-null type
func extractTypeFromSchema(schema map[string]interface{}) string {
// Check for direct type
if paramType, ok := schema["type"].(string); ok {
return paramType
}
// Check for oneOf
if oneOf, ok := schema["oneOf"].([]interface{}); ok {
for _, item := range oneOf {
if itemMap, ok := item.(map[string]interface{}); ok {
if itemType, ok := itemMap["type"].(string); ok {
// Skip null type, return the first non-null type found
if itemType != "null" {
return itemType
}
}
}
}
}
return ""
}
func getParameters(input map[string]interface{}) []interface{} { func getParameters(input map[string]interface{}) []interface{} {
var emptySlice []interface{} var emptySlice []interface{}
methods := []string{"get", "post", "put", "delete", "patch", "head", "options"} methods := []string{"get", "post", "put", "delete", "patch", "head", "options"}
@@ -35,7 +60,6 @@ func getParameters(input map[string]interface{}) []interface{} {
var result []interface{} var result []interface{}
//Check for requestBody
if requestBody, ok := parameters["requestBody"].(map[string]interface{}); ok { if requestBody, ok := parameters["requestBody"].(map[string]interface{}); ok {
if content, ok := requestBody["content"].(map[string]interface{}); ok { if content, ok := requestBody["content"].(map[string]interface{}); ok {
// Check for application/x-www-form-urlencoded, application/json, or multipart/form-data // Check for application/x-www-form-urlencoded, application/json, or multipart/form-data
@@ -76,13 +100,27 @@ func getParameters(input map[string]interface{}) []interface{} {
} }
newParam := make(map[string]interface{}) newParam := make(map[string]interface{})
newParam["name"] = name newParam["name"] = name
if propType, ok := propMap["type"].(string); ok { propType := extractTypeFromSchema(propMap)
if propType != "" {
newParam["type"] = propType newParam["type"] = propType
} }
newParam["required"] = requiredFields[name] newParam["required"] = requiredFields[name]
if propType, ok := propMap["type"].(string); ok && propType == "array" { if propType == "array" {
// Try to get items from propMap first
if items, ok := propMap["items"].(map[string]interface{}); ok { if items, ok := propMap["items"].(map[string]interface{}); ok {
newParam["items"] = items newParam["items"] = items
} else if oneOf, ok := propMap["oneOf"].([]interface{}); ok {
// If items not in propMap, try to get from oneOf array element
for _, item := range oneOf {
if itemMap, ok := item.(map[string]interface{}); ok {
if itemType, ok := itemMap["type"].(string); ok && itemType == "array" {
if items, ok := itemMap["items"].(map[string]interface{}); ok {
newParam["items"] = items
break
}
}
}
}
} }
} }
result = append(result, newParam) result = append(result, newParam)
@@ -104,12 +142,24 @@ func getParameters(input map[string]interface{}) []interface{} {
newParam["name"] = name newParam["name"] = name
} }
if schema, ok := param["schema"].(map[string]interface{}); ok { if schema, ok := param["schema"].(map[string]interface{}); ok {
if paramType, ok := schema["type"].(string); ok { paramType := extractTypeFromSchema(schema)
if paramType != "" {
newParam["type"] = paramType newParam["type"] = paramType
} }
if paramType, ok := schema["type"].(string); ok && paramType == "array" { if paramType == "array" {
if items, ok := schema["items"].(map[string]interface{}); ok { if items, ok := schema["items"].(map[string]interface{}); ok {
newParam["items"] = items newParam["items"] = items
} else if oneOf, ok := schema["oneOf"].([]interface{}); ok {
for _, item := range oneOf {
if itemMap, ok := item.(map[string]interface{}); ok {
if itemType, ok := itemMap["type"].(string); ok && itemType == "array" {
if items, ok := itemMap["items"].(map[string]interface{}); ok {
newParam["items"] = items
break
}
}
}
}
} }
} }
} }