v1.16.5
This commit is contained in:
102
CHANGELOG.md
102
CHANGELOG.md
@@ -1,4 +1,4 @@
|
|||||||
## Version 1.16.4
|
## Version 1.16.5
|
||||||
|
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
@@ -18,98 +18,62 @@
|
|||||||
| `rg/AccessRevoke` | :heavy_check_mark: | :heavy_check_mark: |
|
| `rg/AccessRevoke` | :heavy_check_mark: | :heavy_check_mark: |
|
||||||
| `sep/ConfigFieldEdit` | :x: | :heavy_check_mark: |
|
| `sep/ConfigFieldEdit` | :x: | :heavy_check_mark: |
|
||||||
|
|
||||||
|
|
||||||
### Добавлено
|
### Добавлено
|
||||||
|
|
||||||
#### apiaccess
|
#### audit
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1055 | Структура `SDNEndpoints` и опциональное поле `SDN` в структуру `APIsEndpoints` в cloudbroker/apiaccess |
|
| BGOS-1072 | Вычисляемые поля `ResgroupID`, `AccountID`, `ComputeID`, `VINSID`, `ServiceID`, `K8SID`, `FLIPGroupID`, `LBID`, `SEPID`, `NodeIDs`, `DiskIDs` и `APITask` в структуру ответа `ItemAudit` в cloudapi/audit |
|
||||||
| BGOS-1055 | Опциональные поля `Audit`, `DPDKNet`, `SecurityGroup`, `SEP`, `StoragePolicy`, `Trunk`, `VFPool`, `VMFolder`, `Zone` в структуру `CloudAPIEndpoints` в cloudbroker/apiaccess |
|
| BGOS-1072 | Вычисляемые поля `ResgroupID`, `AccountID`, `ComputeID`, `VINSID`, `ServiceID`, `K8SID`, `FLIPGroupID`, `LBID`, `SEPID`, `NodeIDs`, `DiskIDs` и `APITask` в структуру ответа `ItemAudit` в cloudbroker/audit |
|
||||||
| BGOS-1055 | Опциональные поля `Backup`, `DPDKNet`, `SecurityGroup`, `StoragePolicy`, `Trunk`, `VFPool`, `VMFolder`, `Zone` в структуру `CloudBrokerEndpoints` в cloudbroker/apiaccess |
|
|
||||||
| BGOS-1055 | Опциональные поля `Cache`, `InfoWellknown` в структуру `SystemEndpoints` в cloudbroker/apiaccess |
|
|
||||||
|
|
||||||
#### compute
|
#### compute
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1043 | Опциональное поле `AsyncMode` в структуру запроса `SnapshotEvictDiskRequest` в cloudbroker/compute |
|
| BGOS-1069 | Вычисляемое поле `FolderID` в структуры ответа `RecordCompute` и `ItemCompute` в cloudapi/compute |
|
||||||
| BGOS-1044 | Методы `AsyncAffinityRuleAdd` и `AsyncAntiAffinityRuleAdd` в cloudapi/compute и cloudbroker/compute |
|
| BGOS-1069 | Вычисляемое поле `FolderID` в структуры ответа `RecordCompute` и `InfoCompute` в cloudapi/compute |
|
||||||
| BGOS-1054 | Опциональные поля `FolderID` и `IncludeDescendants` в структуру запроса `ListRequest` в cloudapi/compute |
|
| BGOS-1068 | Структуры ответа `MigrationReport`, `MigrationReportItem`, `AffinityRuleAddResult` и `AntiAffinityRuleAddResult` в cloudapi/compute |
|
||||||
| BGOS-1054 | Опциональные поля `FolderID` и `IncludeDescendants` в структуру запроса `ListRequest` в cloudbroker/compute |
|
| BGOS-1068 | Структуры ответа `MigrationReport`, `MigrationReportItem`, `AffinityRuleAddResult` и `AntiAffinityRuleAddResult` в cloudbroker/compute |
|
||||||
| BGOS-1046 | Опциональное поле `Migrate` в структуры запросов `AffinityRuleAddRequest` и `AntiAffinityRuleAddRequest` в cloudapi/compute |
|
| BGOS-1063 | Структуры запроса `MigrateV2Request`, `MigrateV2AbortRequest`, `MigrateV2CleanupRequest`, `MigrateV2GetRequest`, `MigrateV2ListRequest` и `MigrateV2ResolveRequest` и методы `MigrateV2`, `MigrateV2Abort`, `MigrateV2Cleanup`, `MigrateV2Get`, `MigrateV2List` и `MigrateV2ResolveRequest` в cloudbroker/compute |
|
||||||
| BGOS-1046 | Опциональное поле `Migrate` в структуры запросов `AffinityRuleAddRequest` и `AntiAffinityRuleAddRequest` в cloudbroker/compute |
|
| BGOS-1080 | Опциональное поле `AccountID` из структуры запроса `CreateTemplateFromBlankRequest` в cloudapi/compute |
|
||||||
|
|
||||||
#### session
|
|
||||||
| Идентификатор задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-1048 | Опциональное поле `IncludeArchive` в структуру запроса `ListRequest` в cloudbroker/session |
|
|
||||||
|
|
||||||
#### stpolicy
|
|
||||||
| Идентификатор задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-1047 | Вычисляемое поле `ReplicationProfileID` в структуры ответа `InfoStoragePolicy` и `ItemStoragePolicy` в cloudapi/stpolicy и в cloudbroker/stpolicy |
|
|
||||||
| BGOS-1047 | Вычисляемое поле `ReplicationProfileID` в структуру ответа `InfoStoragePolicyWithID` в cloudbroker/stpolicy |
|
|
||||||
| BGOS-1047 | Методы `GetReplicationProfile`, `ListReplicationProfile`, структуры запроса `GetReplicationProfileRequest`, `ListReplicationProfileRequest` и структуры ответа `InfoReplicationProfile`, `ListReplicationProfiles`, `ItemReplicationProfile`, `ListSchedules`, `Schedule`, `Calendar` в cloudapi/stpolicy и в cloudbroker/stpolicy |
|
|
||||||
| BGOS-1047 | Метод `CreateReplicationProfile`, структуры запроса `CreateReplicationProfileRequest`, `SchedulesRequest`, `CalendarRequest` в cloudbroker/stpolicy |
|
|
||||||
| BGOS-1047 | Метод `UpdateReplicationProfile`, структуры запроса `UpdateReplicationProfileRequest`, `ConfigRequest` в cloudbroker/stpolicy |
|
|
||||||
| BGOS-1047 | Метод `DeleteReplicationProfile` и структура запроса `DeleteReplicationProfileRequest` в cloudbroker/stpolicy |
|
|
||||||
| BGOS-1047 | Методы `AddAccessReplicationProfile`, `RevokeAccessReplicationProfile` и структуры запроса `AddAccessReplicationProfileRequest`, `RevokeAccessReplicationProfileRequest` в cloudbroker/stpolicy |
|
|
||||||
|
|
||||||
#### vmfolder
|
|
||||||
| Идентификатор задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-1049 | Группа апи методов vmfolder в cloudapi и cloudbroker |
|
|
||||||
|
|
||||||
### Изменено
|
|
||||||
|
|
||||||
#### backup
|
|
||||||
| Идентификатор задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-1045 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структурах запроса `CreateDiskBackupRequest`, `CreateDisksBackupRequest`, `DeleteDiskBackupRequest`, `RestoreDiskFromBackupRequest` и `RestoreDisksFromBackupRequest` в cloudbroker/backup |
|
|
||||||
|
|
||||||
#### compute
|
|
||||||
| Идентификатор задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-1043 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структурах запроса `AbortSharedSnapshotMergeRequest`, `CDEjectRequest`, `CDInsertRequest`, `ChangeIPRequest`, `ChangeLinkStateRequest`, `ChangeMTURequest`, `ChangeQoSPoliciesRequest`, `ChangeSecGroupsRequest`, `CloneRequest`, `CreateTemplateRequest`, `CreateTemplateFromBlankRequest`, `DeleteRequest`, `DisableRequest`, `DiskAddRequest`, `DiskAttachRequest`, `DiskDelRequest`, `DiskDetachRequest`, `DiskQOSRequest`, `DiskResizeRequest`, `DiskSwitchToReplicationRequest`, `GuestAgentDisableRequest`, `GuestAgentEnableRequest`, `GuestAgentExecuteRequest`, `GuestAgentFeatureUpdateRequest`, `MigrateToZoneRequest`, `MoveToRGRequest`, `NetAttachRequest`, `NetDetachRequest`, `PauseRequest`, `PFWAddRequest`, `PFWDelRequest`, `PinToNodeRequest`, `PowerCycleRequest`, `RebootRequest`, `RedeployRequest`, `ResetRequest`, `ResizeRequest`, `RestoreRequest`, `ResumeRequest`, `SnapshotCreateRequest`, `SnapshotDeleteRequest`, `SnapshotRollbackRequest`, `StartRequest` и `StopRequest` в cloudapi/compute |
|
|
||||||
| BGOS-1043 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структурах запроса `AbortSharedSnapshotMergeRequest`, `CDEjectRequest`, `CDInsertRequest`, `ChangeIPRequest`, `ChangeLinkStateRequest`, `ChangeMTURequest`, `ChangeQoSPoliciesRequest`, `ChangeSecGroupsRequest`, `CloneRequest`, `CreateTemplateRequest`, `CreateTemplateFromBlankRequest`, `DeleteRequest`, `DisableRequest`, `DiskAddRequest`, `DiskAttachRequest`, `DiskDelRequest`, `DiskDetachRequest`, `DiskQOSRequest`, `DiskResizeRequest`, `DiskSwitchToReplicationRequest`, `GuestAgentDisableRequest`, `GuestAgentEnableRequest`, `GuestAgentExecuteRequest`, `GuestAgentFeatureUpdateRequest`, `MassDeleteRequest`, `MassRebootRequest`, `MassStartRequest`, `MassStopRequest`, `MigrateAbortRequest`, `MigrateStorageAbortRequest`, `MigrateStorageCleanUpRequest`, `MigrateToZoneRequest`, `MoveToRGRequest`, `NetAttachRequest`, `NetDetachRequest`, `NetQOSRequest`, `PauseRequest`, `PFWAddRequest`, `PFWDelRequest`, `PinToNodeRequest`, `PowerCycleRequest`, `RaiseDownRequest`, `RebootRequest`, `RedeployRequest`, `ResetRequest`, `ResizeRequest`, `RestoreRequest`, `ResumeRequest`, `SnapshotCreateRequest`, `SnapshotDeleteRequest`, `SnapshotRollbackRequest`, `StartRequest` и `StopRequest` в cloudbroker/compute |
|
|
||||||
| BGOS-1043 | Опциональное поле `SyncMode` на `AsyncMode` в структуре запроса `MigrateRequest` в cloudbroker/compute |
|
|
||||||
| BGOS-1043 | Опциональное поле `Sync` на `Async` в структуре запроса `MigrateStorageRequest` в cloudbroker/compute |
|
|
||||||
|
|
||||||
#### disks
|
#### disks
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1045 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `FromPlatformDiskRequest` в cloudapi/disks и в cloudbroker/disks |
|
| BGOS-1080 | Опциональное поле `AccountID` из структуры запроса `FromPlatformDiskRequest` в cloudapi/disks |
|
||||||
|
|
||||||
#### image
|
#### extnet
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1045 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `CreateRequest` в cloudapi/image и в cloudbroker/image |
|
| BGOS-1073 | Вычисляемое поле `AutoAssignable` в структуру ответа `ItemReservation` в cloudapi/extnet |
|
||||||
| BGOS-1045 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `CreateCDROMImageRequest` в cloudbroker/image |
|
| BGOS-1073 | Вычисляемые поля `AccountID` и `AutoAssignable` в структуру ответа `Excluded` в cloudapi/extnet |
|
||||||
|
| BGOS-1073 | Вычисляемое поле `AutoAssignable` в структуру ответа `ItemReservation` в cloudbroker/extnet |
|
||||||
|
|
||||||
|
#### grid
|
||||||
|
| Идентификатор задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BGOS-1074 | Вычисляемое поле `VMFoldersEnabled` в структуры ответа `RecordGrid` и `ItemGridList` в cloudbroker/grid |
|
||||||
|
|
||||||
#### kvmx86
|
#### kvmx86
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1045 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `MassCreateRequest` в cloudbroker/kvmx86 |
|
| BGOS-1067 | Опциональное поле `PCIdevices` в структуры запросов `CreateRequest` и `CreateBlankRequest` в cloudapi/kvmx86 |
|
||||||
|
| BGOS-1067 | Опциональное поле `PCIdevices` в структуры запросов `CreateRequest` и `CreateBlankRequest` в cloudbroker/kvmx86 |
|
||||||
|
| BGOS-1081 | Опциональное поле `VGPUs` в структуры запросов `CreateRequest` и `CreateBlankRequest` в cloudapi/kvmx86 |
|
||||||
|
| BGOS-1081 | Опциональное поле `VGPUs` в структуры запросов `CreateRequest` и `CreateBlankRequest` в cloudbroker/kvmx86 |
|
||||||
|
|
||||||
#### node
|
### Изменено
|
||||||
| Идентификатор задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-1045 | JSON-тэг опционального поля `AsyncMode` с `asyncMode` на `async_mode` в структуре запроса `EnableRequest` в cloudbroker/node |
|
|
||||||
|
|
||||||
### Исправлено
|
|
||||||
|
|
||||||
#### apiaccess
|
#### apiaccess
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1055 | Ошибка при вызове метода `Update` в cloudbroker/apiaccess |
|
| BGOS-1082 | Тип поля `APIs` с опционального на обязательный в структуре запроса `UpdateRequest` в cloudbroker/apiaccess |
|
||||||
| BGOS-1055 | Исправлен тип ответа метода `DescUpdate` в cloudbroker/apiaccess |
|
|
||||||
|
|
||||||
|
#### compute
|
||||||
#### Удалено
|
|
||||||
|
|
||||||
#### apiaccess
|
|
||||||
| Идентификатор задачи | Описание |
|
| Идентификатор задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-1055 | Структура `LibCloudEndpoints` и опциональное поле `LibCloud` из структуры `APIsEndpoints` в cloudbroker/apiaccess |
|
| BGOS-1068 | Тип ответа метода `AffinityRuleAdd` с `bool` на структуру `AffinityRuleAddResult` в cloudapi/compute |
|
||||||
| BGOS-1055 | Опциональные поля `CloudSpace`, `ComputeCI`, `DPDK`, `Machine`, `Openshift`, `OpenshiftCI`, `PortForwarding`, `Sizes` из структуры `CloudAPIEndpoints` в cloudbroker/apiaccess |
|
| BGOS-1068 | Тип ответа метода `AffinityRuleAdd` с `bool` на структуру `AffinityRuleAddResult` в cloudbroker/compute |
|
||||||
| BGOS-1055 | Опциональные поля `CloudSpace`, `ComputeCI`, `Desnode`, `Diagnostics`, `DPDK`, `IaaS`, `Machine`, `Openshift`, `OpenshiftCI`, `Ovsnode`, `QOS` из структуры `CloudBrokerEndpoints` в cloudbroker/apiaccess |
|
| BGOS-1068 | Тип ответа метода `AntiAffinityRuleAdd` с `bool` на структуру `AntiAffinityRuleAddResult` в cloudapi/compute |
|
||||||
| BGOS-1055 | Опциональные поля `AgentController`, `Alerts`, `ErrorConditionHandler`, `Job`, `Log`, `Logo` из структуры `SystemEndpoints` в cloudbroker/apiaccess |
|
| BGOS-1068 | Тип ответа метода `AntiAffinityRuleAdd` с `bool` на структуру `AntiAffinityRuleAddResult` в cloudbroker/compute |
|
||||||
|
|
||||||
|
|||||||
@@ -500,3 +500,8 @@ func memoryBalloonModeValidator(fe validator.FieldLevel) bool {
|
|||||||
|
|
||||||
return IsInSlice(fieldValue, memoryBalloonModeValues)
|
return IsInSlice(fieldValue, memoryBalloonModeValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func migrateV2ModeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
return IsInSlice(fieldValue, migrateV2ModeValues)
|
||||||
|
}
|
||||||
|
|||||||
@@ -336,5 +336,7 @@ func registerAllValidators(validate *validator.Validate) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("migrateV2Mode", migrateV2ModeValidator)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ var (
|
|||||||
watchdogActionValues = []string{"reset", "shutdown", "poweroff", "pause", "none"}
|
watchdogActionValues = []string{"reset", "shutdown", "poweroff", "pause", "none"}
|
||||||
|
|
||||||
memoryBalloonModeValues = []string{"auto", "legacy", "none"}
|
memoryBalloonModeValues = []string{"auto", "legacy", "none"}
|
||||||
|
|
||||||
|
migrateV2ModeValues = []string{"compute", "disks", "compute_and_disks"}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -88,6 +88,42 @@ type ItemAudit struct {
|
|||||||
|
|
||||||
// TTL
|
// TTL
|
||||||
TTL string `json:"_ttl"`
|
TTL string `json:"_ttl"`
|
||||||
|
|
||||||
|
// Resource group ID
|
||||||
|
ResgroupID uint64 `json:"resgroup_id"`
|
||||||
|
|
||||||
|
// Account ID
|
||||||
|
AccountID uint64 `json:"account_id"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// VINS ID
|
||||||
|
VINSID uint64 `json:"vins_id"`
|
||||||
|
|
||||||
|
// Service ID
|
||||||
|
ServiceID uint64 `json:"service_id"`
|
||||||
|
|
||||||
|
// K8S ID
|
||||||
|
K8SID uint64 `json:"k8s_id"`
|
||||||
|
|
||||||
|
// FLIPGroup ID
|
||||||
|
FLIPGroupID uint64 `json:"flipgroup_id"`
|
||||||
|
|
||||||
|
// Load balancer ID
|
||||||
|
LBID uint64 `json:"lb_id"`
|
||||||
|
|
||||||
|
// SEP ID
|
||||||
|
SEPID uint64 `json:"sep_id"`
|
||||||
|
|
||||||
|
// Node IDs
|
||||||
|
NodeIDs []uint64 `json:"node_ids"`
|
||||||
|
|
||||||
|
// Persistent disk IDs associated with the operation
|
||||||
|
DiskIDs []uint64 `json:"disk_ids"`
|
||||||
|
|
||||||
|
// API task ID for asynchronous calls
|
||||||
|
APITask string `json:"apitask"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of audits
|
// List of audits
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"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/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,14 +52,14 @@ type AffinityRuleAddRequest struct {
|
|||||||
type wrapperAffinityRuleAddRequest struct {
|
type wrapperAffinityRuleAddRequest struct {
|
||||||
AffinityRuleAddRequest
|
AffinityRuleAddRequest
|
||||||
|
|
||||||
AsyncMode bool `url:"async_mode"`
|
AsyncMode bool `url:"async_mode" json:"async_mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AffinityRuleAdd add affinity rule
|
// AffinityRuleAdd add affinity rule
|
||||||
func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (bool, error) {
|
func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (AffinityRuleAddResult, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, validators.ValidationErrors(validators.GetErrors(err))
|
return AffinityRuleAddResult{}, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/compute/affinityRuleAdd"
|
url := "/cloudapi/compute/affinityRuleAdd"
|
||||||
@@ -68,17 +69,24 @@ func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest
|
|||||||
AsyncMode: false,
|
AsyncMode: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return AffinityRuleAddResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
if !req.Migrate {
|
||||||
if err != nil {
|
result, err := strconv.ParseBool(string(res))
|
||||||
return false, err
|
return AffinityRuleAddResult{Ok: result}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
var report MigrationReport
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &report)
|
||||||
|
if err != nil {
|
||||||
|
return AffinityRuleAddResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AffinityRuleAddResult{Ok: report.Applied, MigrationReport: &report}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsyncAffinityRuleAdd add affinity rule in async mode
|
// AsyncAffinityRuleAdd add affinity rule in async mode
|
||||||
@@ -95,7 +103,7 @@ func (c Compute) AsyncAffinityRuleAdd(ctx context.Context, req AffinityRuleAddRe
|
|||||||
AsyncMode: true,
|
AsyncMode: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"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/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,14 +52,14 @@ type AntiAffinityRuleAddRequest struct {
|
|||||||
type wrapperAntiAffinityRuleAddRequest struct {
|
type wrapperAntiAffinityRuleAddRequest struct {
|
||||||
AntiAffinityRuleAddRequest
|
AntiAffinityRuleAddRequest
|
||||||
|
|
||||||
AsyncMode bool `url:"async_mode"`
|
AsyncMode bool `url:"async_mode" json:"async_mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AntiAffinityRuleAdd add anti affinity rule
|
// AntiAffinityRuleAdd add anti affinity rule
|
||||||
func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (bool, error) {
|
func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (AntiAffinityRuleAddResult, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, validators.ValidationErrors(validators.GetErrors(err))
|
return AntiAffinityRuleAddResult{}, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/compute/antiAffinityRuleAdd"
|
url := "/cloudapi/compute/antiAffinityRuleAdd"
|
||||||
@@ -68,17 +69,24 @@ func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAd
|
|||||||
AsyncMode: false,
|
AsyncMode: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return AntiAffinityRuleAddResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
if !req.Migrate {
|
||||||
if err != nil {
|
result, err := strconv.ParseBool(string(res))
|
||||||
return false, err
|
return AntiAffinityRuleAddResult{Ok: result}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
var report MigrationReport
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &report)
|
||||||
|
if err != nil {
|
||||||
|
return AntiAffinityRuleAddResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AntiAffinityRuleAddResult{Ok: report.Applied, MigrationReport: &report}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsyncAntiAffinityRuleAdd add anti affinity rule in async mode
|
// AsyncAntiAffinityRuleAdd add anti affinity rule in async mode
|
||||||
@@ -95,7 +103,7 @@ func (c Compute) AsyncAntiAffinityRuleAdd(ctx context.Context, req AntiAffinityR
|
|||||||
AsyncMode: true,
|
AsyncMode: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,6 @@ type CreateTemplateFromBlankRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
Password string `url:"password,omitempty" json:"password,omitempty"`
|
Password string `url:"password,omitempty" json:"password,omitempty"`
|
||||||
|
|
||||||
// Account ID to make the image exclusive
|
|
||||||
// Required: false
|
|
||||||
AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"`
|
|
||||||
|
|
||||||
// Pool for image create
|
// Pool for image create
|
||||||
// Required: false
|
// Required: false
|
||||||
PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"`
|
PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"`
|
||||||
|
|||||||
@@ -575,6 +575,9 @@ type RecordCompute struct {
|
|||||||
// Zone ID
|
// Zone ID
|
||||||
// Required: false
|
// Required: false
|
||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
|
|
||||||
|
// Folder ID
|
||||||
|
FolderID uint64 `json:"folder_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detailed information about ACL Access in a compute
|
// Detailed information about ACL Access in a compute
|
||||||
@@ -1564,6 +1567,9 @@ type ItemCompute struct {
|
|||||||
|
|
||||||
// Zone ID
|
// Zone ID
|
||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
|
|
||||||
|
// Folder ID
|
||||||
|
FolderID uint64 `json:"folder_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListInfoDisks
|
// ListInfoDisks
|
||||||
@@ -1743,3 +1749,47 @@ type CloneStatus struct {
|
|||||||
// Progress percent
|
// Progress percent
|
||||||
ProgressPercent int `json:"progress_percent"`
|
ProgressPercent int `json:"progress_percent"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MigrationReportItem struct {
|
||||||
|
// ID of the compute instance
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// Per-VM action result, not workflow status
|
||||||
|
// Should be one of:
|
||||||
|
// - migrated: migration completed; the rule may still be unsatisfied
|
||||||
|
// - skipped: migration was not needed or applicable
|
||||||
|
// - not_started: submission was not attempted
|
||||||
|
// - not_completed: completion is unconfirmed; the VM may have moved
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Action details, errors and final rule-placement warnings
|
||||||
|
Message string `json:"message"`
|
||||||
|
|
||||||
|
// Workflow ID for tracking, or nil if submission was not attempted.
|
||||||
|
// A non-nil ID does not confirm job acceptance
|
||||||
|
WorkflowJobID *string `json:"workflow_job_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrationReport struct {
|
||||||
|
// Rules were saved; does not confirm migration success or rule satisfaction
|
||||||
|
Applied bool `json:"applied"`
|
||||||
|
|
||||||
|
// Per-compute migration results
|
||||||
|
Migrations []MigrationReportItem `json:"migrations"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AffinityRuleAddResult struct {
|
||||||
|
// Result of the rule addition
|
||||||
|
Ok bool
|
||||||
|
|
||||||
|
// Migration report. Populated only when the request was made with Migrate=true, nil otherwise
|
||||||
|
MigrationReport *MigrationReport
|
||||||
|
}
|
||||||
|
|
||||||
|
type AntiAffinityRuleAddResult struct {
|
||||||
|
// Result of the rule addition
|
||||||
|
Ok bool
|
||||||
|
|
||||||
|
// Migration report. Populated only when the request was made with Migrate=true, nil otherwise
|
||||||
|
MigrationReport *MigrationReport
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ type FromPlatformDiskRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
Password string `url:"password,omitempty" json:"password,omitempty"`
|
Password string `url:"password,omitempty" json:"password,omitempty"`
|
||||||
|
|
||||||
// Account ID to make the image exclusive
|
|
||||||
// Required: false
|
|
||||||
AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"`
|
|
||||||
|
|
||||||
// Pool for image create
|
// Pool for image create
|
||||||
// Required: false
|
// Required: false
|
||||||
PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"`
|
PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"`
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ type ItemReservation struct {
|
|||||||
// Account ID
|
// Account ID
|
||||||
AccountID uint64 `json:"account_id"`
|
AccountID uint64 `json:"account_id"`
|
||||||
|
|
||||||
|
// Auto assignable
|
||||||
|
AutoAssignable bool `json:"auto_assignable"`
|
||||||
|
|
||||||
// ClientType
|
// ClientType
|
||||||
ClientType string `json:"clientType"`
|
ClientType string `json:"clientType"`
|
||||||
|
|
||||||
@@ -127,6 +130,12 @@ type VNFs struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Excluded struct {
|
type Excluded struct {
|
||||||
|
// Account ID
|
||||||
|
AccountID uint64 `json:"account_id"`
|
||||||
|
|
||||||
|
// Auto assignable
|
||||||
|
AutoAssignable bool `json:"auto_assignable"`
|
||||||
|
|
||||||
// ClientType
|
// ClientType
|
||||||
ClientType string `json:"clientType"`
|
ClientType string `json:"clientType"`
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,10 @@ type CreateRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
||||||
|
|
||||||
|
// List of PCI device IDs to attach to this VM
|
||||||
|
// Required: false
|
||||||
|
PCIdevices []uint64 `url:"pcidevices,omitempty" json:"pcidevices,omitempty"`
|
||||||
|
|
||||||
// Zone ID
|
// Zone ID
|
||||||
// Required: false
|
// Required: false
|
||||||
ZoneID uint64 `url:"zoneId,omitempty" json:"zoneId,omitempty"`
|
ZoneID uint64 `url:"zoneId,omitempty" json:"zoneId,omitempty"`
|
||||||
@@ -252,6 +256,10 @@ type CreateRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
// Default: "auto"
|
// Default: "auto"
|
||||||
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
||||||
|
|
||||||
|
// List of vGPU IDs to attach to the VM
|
||||||
|
// Required: false
|
||||||
|
VGPUs []uint64 `url:"vgpus,omitempty" json:"vgpus,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRAM returns RAM field values
|
// GetRAM returns RAM field values
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ type CreateBlankRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
||||||
|
|
||||||
|
// List of PCI device IDs to attach to this VM
|
||||||
|
// Required: false
|
||||||
|
PCIdevices []uint64 `url:"pcidevices,omitempty" json:"pcidevices,omitempty"`
|
||||||
|
|
||||||
// VM type linux, windows or unknown
|
// VM type linux, windows or unknown
|
||||||
// Required: false
|
// Required: false
|
||||||
LoaderType string `url:"loaderType,omitempty" json:"loaderType,omitempty" validate:"omitempty,loaderType"`
|
LoaderType string `url:"loaderType,omitempty" json:"loaderType,omitempty" validate:"omitempty,loaderType"`
|
||||||
@@ -134,6 +138,10 @@ type CreateBlankRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
// Default: "auto"
|
// Default: "auto"
|
||||||
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
||||||
|
|
||||||
|
// List of vGPU IDs to attach to the VM
|
||||||
|
// Required: false
|
||||||
|
VGPUs []uint64 `url:"vgpus,omitempty" json:"vgpus,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRAM returns RAM field values
|
// GetRAM returns RAM field values
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type UpdateRequest struct {
|
|||||||
APIAccessID uint64 `url:"apiaccess_id" json:"apiaccess_id" validate:"required"`
|
APIAccessID uint64 `url:"apiaccess_id" json:"apiaccess_id" validate:"required"`
|
||||||
|
|
||||||
// APIs to remove from APIAccess group
|
// APIs to remove from APIAccess group
|
||||||
// Required: false
|
// Required: true
|
||||||
APIs APIsEndpoints `url:"-" json:"-"`
|
APIs APIsEndpoints `url:"-" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,42 @@ type ItemAudit struct {
|
|||||||
|
|
||||||
// TTL
|
// TTL
|
||||||
TTL string `json:"_ttl"`
|
TTL string `json:"_ttl"`
|
||||||
|
|
||||||
|
// Resource group ID
|
||||||
|
ResgroupID uint64 `json:"resgroup_id"`
|
||||||
|
|
||||||
|
// Account ID
|
||||||
|
AccountID uint64 `json:"account_id"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// VINS ID
|
||||||
|
VINSID uint64 `json:"vins_id"`
|
||||||
|
|
||||||
|
// Service ID
|
||||||
|
ServiceID uint64 `json:"service_id"`
|
||||||
|
|
||||||
|
// K8S ID
|
||||||
|
K8SID uint64 `json:"k8s_id"`
|
||||||
|
|
||||||
|
// FLIPGroup ID
|
||||||
|
FLIPGroupID uint64 `json:"flipgroup_id"`
|
||||||
|
|
||||||
|
// Load balancer ID
|
||||||
|
LBID uint64 `json:"lb_id"`
|
||||||
|
|
||||||
|
// SEP ID
|
||||||
|
SEPID uint64 `json:"sep_id"`
|
||||||
|
|
||||||
|
// Node IDs
|
||||||
|
NodeIDs []uint64 `json:"node_ids"`
|
||||||
|
|
||||||
|
// Persistent disk IDs associated with the operation
|
||||||
|
DiskIDs []uint64 `json:"disk_ids"`
|
||||||
|
|
||||||
|
// API task ID for asynchronous calls
|
||||||
|
APITask string `json:"apitask"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of audits
|
// List of audits
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"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/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,14 +54,14 @@ type AffinityRuleAddRequest struct {
|
|||||||
type wrapperAffinityRuleAddRequest struct {
|
type wrapperAffinityRuleAddRequest struct {
|
||||||
AffinityRuleAddRequest
|
AffinityRuleAddRequest
|
||||||
|
|
||||||
AsyncMode bool `url:"async_mode"`
|
AsyncMode bool `url:"async_mode" json:"async_mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AffinityRuleAdd adds affinity rule
|
// AffinityRuleAdd adds affinity rule
|
||||||
func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (bool, error) {
|
func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (AffinityRuleAddResult, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, validators.ValidationErrors(validators.GetErrors(err))
|
return AffinityRuleAddResult{}, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudbroker/compute/affinityRuleAdd"
|
url := "/cloudbroker/compute/affinityRuleAdd"
|
||||||
@@ -70,17 +71,24 @@ func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest
|
|||||||
AsyncMode: false,
|
AsyncMode: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return AffinityRuleAddResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
if !req.Migrate {
|
||||||
if err != nil {
|
result, err := strconv.ParseBool(string(res))
|
||||||
return false, err
|
return AffinityRuleAddResult{Ok: result}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
var report MigrationReport
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &report)
|
||||||
|
if err != nil {
|
||||||
|
return AffinityRuleAddResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AffinityRuleAddResult{Ok: report.Applied, MigrationReport: &report}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsyncAffinityRuleAdd add affinity rule in async mode
|
// AsyncAffinityRuleAdd add affinity rule in async mode
|
||||||
@@ -97,7 +105,7 @@ func (c Compute) AsyncAffinityRuleAdd(ctx context.Context, req AffinityRuleAddRe
|
|||||||
AsyncMode: true,
|
AsyncMode: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"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/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -51,14 +52,14 @@ type AntiAffinityRuleAddRequest struct {
|
|||||||
type wrapperAntiAffinityRuleAddRequest struct {
|
type wrapperAntiAffinityRuleAddRequest struct {
|
||||||
AntiAffinityRuleAddRequest
|
AntiAffinityRuleAddRequest
|
||||||
|
|
||||||
AsyncMode bool `url:"async_mode"`
|
AsyncMode bool `url:"async_mode" json:"async_mode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AntiAffinityRuleAdd adds anti affinity rule
|
// AntiAffinityRuleAdd adds anti affinity rule
|
||||||
func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (bool, error) {
|
func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (AntiAffinityRuleAddResult, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, validators.ValidationErrors(validators.GetErrors(err))
|
return AntiAffinityRuleAddResult{}, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudbroker/compute/antiAffinityRuleAdd"
|
url := "/cloudbroker/compute/antiAffinityRuleAdd"
|
||||||
@@ -68,17 +69,24 @@ func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAd
|
|||||||
AsyncMode: false,
|
AsyncMode: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return AntiAffinityRuleAddResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
if !req.Migrate {
|
||||||
if err != nil {
|
result, err := strconv.ParseBool(string(res))
|
||||||
return false, err
|
return AntiAffinityRuleAddResult{Ok: result}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
var report MigrationReport
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &report)
|
||||||
|
if err != nil {
|
||||||
|
return AntiAffinityRuleAddResult{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return AntiAffinityRuleAddResult{Ok: report.Applied, MigrationReport: &report}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AsyncAntiAffinityRuleAdd add anti affinity rule in async mode
|
// AsyncAntiAffinityRuleAdd add anti affinity rule in async mode
|
||||||
@@ -95,7 +103,7 @@ func (c Compute) AsyncAntiAffinityRuleAdd(ctx context.Context, req AntiAffinityR
|
|||||||
AsyncMode: true,
|
AsyncMode: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, aReq)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, aReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
83
pkg/cloudbroker/compute/migrate_v2.go
Normal file
83
pkg/cloudbroker/compute/migrate_v2.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Target describes a target for migration
|
||||||
|
type Target struct {
|
||||||
|
// SEP ID
|
||||||
|
// Required: true
|
||||||
|
SepID uint64 `url:"sep_id" json:"sep_id" validate:"required"`
|
||||||
|
|
||||||
|
// Name of a pool
|
||||||
|
// Required: true
|
||||||
|
PoolName string `url:"pool_name" json:"pool_name" validate:"required"`
|
||||||
|
|
||||||
|
// Storage policy ID
|
||||||
|
// Required: false
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
|
||||||
|
|
||||||
|
// Disk IDs
|
||||||
|
// Required: false
|
||||||
|
DiskIDs []uint64 `url:"disk_ids,omitempty" json:"disk_ids,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage describes a destination for a disk
|
||||||
|
type Storage struct {
|
||||||
|
// Target for migration
|
||||||
|
// Required: false
|
||||||
|
Targets []Target `url:"targets,omitempty" json:"targets,omitempty"`
|
||||||
|
|
||||||
|
// Whether a separate source-disk cleanup job should be started after full success
|
||||||
|
// Required: false
|
||||||
|
AutoCleanup interface{} `url:"auto_cleanup,omitempty" json:"auto_cleanup,omitempty" validate:"omitempty,isBool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2Request to start a migration of a compute or a disk
|
||||||
|
type MigrateV2Request struct {
|
||||||
|
// ID of compute to migrate
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
|
||||||
|
|
||||||
|
// Stateless load balancers support only compute mode, including their local system disk.
|
||||||
|
// Required: false
|
||||||
|
Mode string `url:"mode,omitempty" json:"mode,omitempty" validate:"omitempty,migrateV2Mode"`
|
||||||
|
|
||||||
|
// ID of node to migrate to
|
||||||
|
// Required: false
|
||||||
|
TargetNodeID uint64 `url:"target_node_id,omitempty" json:"target_node_id,omitempty"`
|
||||||
|
|
||||||
|
// Destination for a disk
|
||||||
|
// Required: false
|
||||||
|
Storage Storage `url:"storage,omitempty" json:"storage,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2 starts a migration of a compute or a disk
|
||||||
|
func (c Compute) MigrateV2(ctx context.Context, req MigrateV2Request) (string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/migrate_v2"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp string
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
47
pkg/cloudbroker/compute/migrate_v2_abort.go
Normal file
47
pkg/cloudbroker/compute/migrate_v2_abort.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateV2AbortRequest to abort a migration of a compute
|
||||||
|
type MigrateV2AbortRequest struct {
|
||||||
|
// Original migration workflow IDs, not agent, cleanup or recovery job IDs
|
||||||
|
// Required: true
|
||||||
|
WorkflowJobIDs []string `url:"workflow_job_ids" json:"workflow_job_ids" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2Abort aborts a migration of a compute
|
||||||
|
func (c Compute) MigrateV2Abort(ctx context.Context, req MigrateV2AbortRequest) (*MigrateV2AbortRecord, error) {
|
||||||
|
res, err := c.MigrateV2AbortRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := MigrateV2AbortRecord{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2AbortRaw aborts a migration of a compute and returns an array of bytes
|
||||||
|
func (c Compute) MigrateV2AbortRaw(ctx context.Context, req MigrateV2AbortRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/migrate_v2_abort"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
41
pkg/cloudbroker/compute/migrate_v2_cleanup.go
Normal file
41
pkg/cloudbroker/compute/migrate_v2_cleanup.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateV2CleanupRequest to clean up after a migration of a compute
|
||||||
|
type MigrateV2CleanupRequest struct {
|
||||||
|
// Original migration workflow IDs, not agent, cleanup or recovery job IDs
|
||||||
|
// Required: true
|
||||||
|
WorkflowJobID string `url:"workflow_job_id" json:"workflow_job_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2Cleanup cleans up after a migration of a compute
|
||||||
|
func (c Compute) MigrateV2Cleanup(ctx context.Context, req MigrateV2CleanupRequest) (string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/migrate_v2_cleanup"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp string
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
46
pkg/cloudbroker/compute/migrate_v2_get.go
Normal file
46
pkg/cloudbroker/compute/migrate_v2_get.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateV2GetRequest to get the information about a workflow job
|
||||||
|
type MigrateV2GetRequest struct {
|
||||||
|
// Original migration workflow IDs
|
||||||
|
// Required: true
|
||||||
|
WorkflowJobID string `url:"workflow_job_id" json:"workflow_job_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2Get gets information about a workflow job as a MigrateV2Record struct
|
||||||
|
func (c Compute) MigrateV2Get(ctx context.Context, req MigrateV2GetRequest) (*MigrateV2Record, error) {
|
||||||
|
res, err := c.MigrateV2GetRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := MigrateV2Record{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRaw gets information about a workflow job as an array of bytes
|
||||||
|
func (c Compute) MigrateV2GetRaw(ctx context.Context, req MigrateV2GetRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/migrate_v2_get"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
67
pkg/cloudbroker/compute/migrate_v2_list.go
Normal file
67
pkg/cloudbroker/compute/migrate_v2_list.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateV2ListRequest to list migrations
|
||||||
|
type MigrateV2ListRequest struct {
|
||||||
|
// Exact APIServer migration workflow job ID
|
||||||
|
// Required: false
|
||||||
|
WorkflowJobID string `url:"workflow_job_id,omitempty" json:"workflow_job_id,omitempty"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
// Required: false
|
||||||
|
ComputeID uint64 `url:"compute_id,omitempty" json:"compute_id,omitempty"`
|
||||||
|
|
||||||
|
// Exact business migration status
|
||||||
|
// Required: false
|
||||||
|
Status string `url:"status,omitempty" json:"status,omitempty"`
|
||||||
|
|
||||||
|
// Source node ID
|
||||||
|
// Required: false
|
||||||
|
SourceNodeID uint64 `url:"source_node_id,omitempty" json:"source_node_id,omitempty"`
|
||||||
|
|
||||||
|
// Target node ID
|
||||||
|
// Required: false
|
||||||
|
TargetNodeID uint64 `url:"target_node_id,omitempty" json:"target_node_id,omitempty"`
|
||||||
|
|
||||||
|
// Whether retained source disks still require cleanup
|
||||||
|
// Required: false
|
||||||
|
CleanupRequired interface{} `url:"cleanup_required,omitempty" json:"cleanup_required,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Page number
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Page size
|
||||||
|
// Required: false
|
||||||
|
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2List gets list of the jobs
|
||||||
|
func (c Compute) MigrateV2List(ctx context.Context, req MigrateV2ListRequest) (*ListMigrateV2, error) {
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/migrate_v2_list"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := ListMigrateV2{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &list, nil
|
||||||
|
}
|
||||||
51
pkg/cloudbroker/compute/migrate_v2_resolve.go
Normal file
51
pkg/cloudbroker/compute/migrate_v2_resolve.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateResolveRequest to resolve a migration
|
||||||
|
type MigrateV2ResolveRequest struct {
|
||||||
|
// Workflow job ID
|
||||||
|
// Required: true
|
||||||
|
WorkflowJobID string `url:"workflow_job_id" json:"workflow_job_id" validate:"required"`
|
||||||
|
|
||||||
|
// Take over cleanup
|
||||||
|
// Required: false
|
||||||
|
TakeOverCleanup interface{} `url:"take_over_cleanup,omitempty" json:"take_over_cleanup,omitempty" validate:"omitempty,isBool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2Resolve resolves a migration of a compute
|
||||||
|
func (c Compute) MigrateV2Resolve(ctx context.Context, req MigrateV2ResolveRequest) (*MigrateV2ResolveRecord, error) {
|
||||||
|
res, err := c.MigrateV2ResolveRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := MigrateV2ResolveRecord{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2ResolveRaw resolves a migration of a compute and returns an array of bytes
|
||||||
|
func (c Compute) MigrateV2ResolveRaw(ctx context.Context, req MigrateV2ResolveRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/migrate_v2_resolve"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -938,6 +938,9 @@ type InfoCompute struct {
|
|||||||
|
|
||||||
// Zone ID
|
// Zone ID
|
||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
|
|
||||||
|
// Folder ID
|
||||||
|
FolderID uint64 `json:"folder_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type QemuQuest struct {
|
type QemuQuest struct {
|
||||||
@@ -1252,6 +1255,9 @@ type RecordCompute struct {
|
|||||||
|
|
||||||
//todo
|
//todo
|
||||||
_ uint64 `json:"nodeId"`
|
_ uint64 `json:"nodeId"`
|
||||||
|
|
||||||
|
// Folder ID
|
||||||
|
FolderID uint64 `json:"folder_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detailed information about ACL Access in a compute
|
// Detailed information about ACL Access in a compute
|
||||||
@@ -2272,3 +2278,376 @@ type CheckComputePlacementItem struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CheckComputePlacementResult map[uint64]CheckComputePlacementItem
|
type CheckComputePlacementResult map[uint64]CheckComputePlacementItem
|
||||||
|
|
||||||
|
type Result struct {
|
||||||
|
// Workflow ID
|
||||||
|
WorkflowJobID string `json:"workflow_job_id"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Job ID
|
||||||
|
JobID string `json:"job_id"`
|
||||||
|
|
||||||
|
// Message
|
||||||
|
Message string `json:"message"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateV2 abort record
|
||||||
|
type MigrateV2AbortRecord struct {
|
||||||
|
// Results
|
||||||
|
Results []Result `json:"results"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Origin struct {
|
||||||
|
// Type
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Correlation ID
|
||||||
|
CorrelationID string `json:"correlation_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Observation struct {
|
||||||
|
// Updated at
|
||||||
|
UpdatedAt uint64 `json:"updated_at"`
|
||||||
|
|
||||||
|
// Agent job ID
|
||||||
|
AgentJobID string `json:"agent_job_id"`
|
||||||
|
|
||||||
|
// Attempt
|
||||||
|
Attempt uint64 `json:"attempt"`
|
||||||
|
|
||||||
|
// Operation
|
||||||
|
Operation string `json:"operation"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Memory struct {
|
||||||
|
// Sampled at
|
||||||
|
SampledAt uint64 `json:"sampled_at"`
|
||||||
|
|
||||||
|
// Percent
|
||||||
|
Percent uint64 `json:"percent"`
|
||||||
|
|
||||||
|
// Bytes per second
|
||||||
|
BytesPerSecond uint64 `json:"bytes_per_second"`
|
||||||
|
|
||||||
|
// Processed bytes
|
||||||
|
ProcessedBytes uint64 `json:"processed_bytes"`
|
||||||
|
|
||||||
|
// Remaining bytes
|
||||||
|
RemainingBytes uint64 `json:"remaining_bytes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProgressDisks struct {
|
||||||
|
// Scope
|
||||||
|
Scope string `json:"scope"`
|
||||||
|
|
||||||
|
// Target devs
|
||||||
|
TargetDevs []string `json:"target_devs"`
|
||||||
|
|
||||||
|
// Sampled at
|
||||||
|
SampledAt uint64 `json:"sampled_at"`
|
||||||
|
|
||||||
|
// Percent
|
||||||
|
Percent uint64 `json:"percent"`
|
||||||
|
|
||||||
|
// Bytes per second
|
||||||
|
BytesPerSecond uint64 `json:"bytes_per_second"`
|
||||||
|
|
||||||
|
// Processed bytes
|
||||||
|
ProcessedBytes uint64 `json:"processed_bytes"`
|
||||||
|
|
||||||
|
// Remaining bytes
|
||||||
|
RemainingBytes uint64 `json:"remaining_bytes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemDisk struct {
|
||||||
|
// Target dev
|
||||||
|
TargetDev string `json:"target_dev"`
|
||||||
|
|
||||||
|
// Sampled at
|
||||||
|
SampledAt uint64 `json:"sampled_at"`
|
||||||
|
|
||||||
|
// Percent
|
||||||
|
Percent uint64 `json:"percent"`
|
||||||
|
|
||||||
|
// Bytes per second
|
||||||
|
BytesPerSecond uint64 `json:"bytes_per_second"`
|
||||||
|
|
||||||
|
// Processed bytes
|
||||||
|
ProcessedBytes uint64 `json:"processed_bytes"`
|
||||||
|
|
||||||
|
// Remaining bytes
|
||||||
|
RemainingBytes uint64 `json:"remaining_bytes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Progress struct {
|
||||||
|
// Observation
|
||||||
|
Observation Observation `json:"observation"`
|
||||||
|
|
||||||
|
// Memory
|
||||||
|
Memory Memory `json:"memory"`
|
||||||
|
|
||||||
|
// Disks
|
||||||
|
Disks ProgressDisks `json:"disks"`
|
||||||
|
|
||||||
|
// System disk
|
||||||
|
SystemDisk SystemDisk `json:"system_disk"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Disk struct {
|
||||||
|
// Source disk ID
|
||||||
|
SourceDiskID uint64 `json:"source_disk_id"`
|
||||||
|
|
||||||
|
// Target disk ID
|
||||||
|
TargetDiskID uint64 `json:"target_disk_id"`
|
||||||
|
|
||||||
|
// Target dev
|
||||||
|
TargetDev string `json:"target_dev"`
|
||||||
|
|
||||||
|
// SEP ID
|
||||||
|
SEPID uint64 `json:"sep_id"`
|
||||||
|
|
||||||
|
// Pool name
|
||||||
|
PoolName string `json:"pool_name"`
|
||||||
|
|
||||||
|
// Storage policy ID
|
||||||
|
StoragePolicyID uint64 `json:"storage_policy_id"`
|
||||||
|
|
||||||
|
// State
|
||||||
|
State string `json:"state"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cleanup struct {
|
||||||
|
// Job ID
|
||||||
|
JobID string `json:"job_id"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Error
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Resolution struct {
|
||||||
|
// Resolved at
|
||||||
|
ResolvedAt string `json:"resolved_at"`
|
||||||
|
|
||||||
|
// Resolved by
|
||||||
|
ResolvedBy string `json:"resolved_by"`
|
||||||
|
|
||||||
|
// RequestID
|
||||||
|
RequestId string `json:"request_id"`
|
||||||
|
|
||||||
|
// Take over cleanup
|
||||||
|
TakeOverCleanup bool `json:"take_over_cleanup"`
|
||||||
|
|
||||||
|
// Previous status
|
||||||
|
PreviousStatus string `json:"previous_status"`
|
||||||
|
|
||||||
|
// Previous cleanup required
|
||||||
|
PreviousCleanupRequired bool `json:"previous_cleanup_required"`
|
||||||
|
|
||||||
|
// Previous error
|
||||||
|
PreviousError string `json:"previous_error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrateV2Item struct {
|
||||||
|
// Workflow Job ID
|
||||||
|
WorkflowJobID string `json:"workflow_job_id"`
|
||||||
|
|
||||||
|
// Mode
|
||||||
|
Mode string `json:"mode"`
|
||||||
|
|
||||||
|
// Origin
|
||||||
|
Origin Origin `json:"origin"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// Progress
|
||||||
|
Progress Progress `json:"progress"`
|
||||||
|
|
||||||
|
// Domain name
|
||||||
|
DomainName string `json:"domain_name"`
|
||||||
|
|
||||||
|
// Domain UUID
|
||||||
|
DomainUUID string `json:"domain_uuid"`
|
||||||
|
|
||||||
|
// Source node ID
|
||||||
|
SourceNodeID uint64 `json:"source_node_id"`
|
||||||
|
|
||||||
|
// Target node ID
|
||||||
|
TargetNodeID uint64 `json:"target_node_id"`
|
||||||
|
|
||||||
|
// Source tech status
|
||||||
|
SourceTechStatus string `json:"source_tech_status"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Migration result confirmed
|
||||||
|
MigrationResultConfirmed bool `json:"migration_result_confirmed"`
|
||||||
|
|
||||||
|
// Disks
|
||||||
|
Disks []Disk `json:"disks"`
|
||||||
|
|
||||||
|
// Disk IDs not copied
|
||||||
|
DiskIDsNotCopied []uint64 `json:"disk_ids_not_copied"`
|
||||||
|
|
||||||
|
// Error
|
||||||
|
Error string `json:"error"`
|
||||||
|
|
||||||
|
// Cleanup required
|
||||||
|
CleanupRequired bool `json:"cleanup_required"`
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
Cleanup Cleanup `json:"cleanup"`
|
||||||
|
|
||||||
|
// Resolution
|
||||||
|
Resolution Resolution `json:"resolution"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListMigrateV2 struct {
|
||||||
|
// Entry count
|
||||||
|
EntryCount uint64 `json:"entry_count"`
|
||||||
|
|
||||||
|
// Data
|
||||||
|
Data []MigrateV2Item `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrateV2Record struct {
|
||||||
|
// Workflow Job ID
|
||||||
|
WorkflowJobID string `json:"workflow_job_id"`
|
||||||
|
|
||||||
|
// Mode
|
||||||
|
Mode string `json:"mode"`
|
||||||
|
|
||||||
|
// Origin
|
||||||
|
Origin Origin `json:"origin"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// Progress
|
||||||
|
Progress Progress `json:"progress"`
|
||||||
|
|
||||||
|
// Domain name
|
||||||
|
DomainName string `json:"domain_name"`
|
||||||
|
|
||||||
|
// Domain UUID
|
||||||
|
DomainUUID string `json:"domain_uuid"`
|
||||||
|
|
||||||
|
// Source node ID
|
||||||
|
SourceNodeID uint64 `json:"source_node_id"`
|
||||||
|
|
||||||
|
// Target node ID
|
||||||
|
TargetNodeID uint64 `json:"target_node_id"`
|
||||||
|
|
||||||
|
// Source tech status
|
||||||
|
SourceTechStatus string `json:"source_tech_status"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Migration result confirmed
|
||||||
|
MigrationResultConfirmed bool `json:"migration_result_confirmed"`
|
||||||
|
|
||||||
|
// Disks
|
||||||
|
Disks []Disk `json:"disks"`
|
||||||
|
|
||||||
|
// Disk IDs not copied
|
||||||
|
DiskIDsNotCopied []uint64 `json:"disk_ids_not_copied"`
|
||||||
|
|
||||||
|
// Error
|
||||||
|
Error string `json:"error"`
|
||||||
|
|
||||||
|
// Cleanup required
|
||||||
|
CleanupRequired bool `json:"cleanup_required"`
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
Cleanup Cleanup `json:"cleanup"`
|
||||||
|
|
||||||
|
// Resolution
|
||||||
|
Resolution Resolution `json:"resolution"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
|
||||||
|
// Logs
|
||||||
|
Logs []string `json:"logs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Migrate V2 resolve record
|
||||||
|
type MigrateV2ResolveRecord struct {
|
||||||
|
// Workflow job ID
|
||||||
|
WorkflowJobID string `json:"workflow_job_id"`
|
||||||
|
|
||||||
|
// Compute ID
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Cleanup required
|
||||||
|
CleanupRequired bool `json:"cleanup_required"`
|
||||||
|
|
||||||
|
// Resolution
|
||||||
|
Resolution Resolution `json:"resolution"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrationReportItem struct {
|
||||||
|
// ID of the compute instance
|
||||||
|
ComputeID uint64 `json:"compute_id"`
|
||||||
|
|
||||||
|
// Per-VM action result, not workflow status
|
||||||
|
// Should be one of:
|
||||||
|
// - migrated: migration completed; the rule may still be unsatisfied
|
||||||
|
// - skipped: migration was not needed or applicable
|
||||||
|
// - not_started: submission was not attempted
|
||||||
|
// - not_completed: completion is unconfirmed; the VM may have moved
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Action details, errors and final rule-placement warnings
|
||||||
|
Message string `json:"message"`
|
||||||
|
|
||||||
|
// Workflow ID for tracking, or nil if submission was not attempted.
|
||||||
|
// A non-nil ID does not confirm job acceptance
|
||||||
|
WorkflowJobID *string `json:"workflow_job_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MigrationReport struct {
|
||||||
|
// Rules were saved; does not confirm migration success or rule satisfaction
|
||||||
|
Applied bool `json:"applied"`
|
||||||
|
|
||||||
|
// Per-compute migration results
|
||||||
|
Migrations []MigrationReportItem `json:"migrations"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AffinityRuleAddResult struct {
|
||||||
|
// Result of the rule addition
|
||||||
|
Ok bool
|
||||||
|
|
||||||
|
// Migration report. Populated only when the request was made with Migrate=true, nil otherwise
|
||||||
|
MigrationReport *MigrationReport
|
||||||
|
}
|
||||||
|
|
||||||
|
type AntiAffinityRuleAddResult struct {
|
||||||
|
// Result of the rule addition
|
||||||
|
Ok bool
|
||||||
|
|
||||||
|
// Migration report. Populated only when the request was made with Migrate=true, nil otherwise
|
||||||
|
MigrationReport *MigrationReport
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,12 +20,21 @@ type ItemReservation struct {
|
|||||||
// Account ID
|
// Account ID
|
||||||
AccountID uint64 `json:"account_id"`
|
AccountID uint64 `json:"account_id"`
|
||||||
|
|
||||||
|
// Auto assignable
|
||||||
|
AutoAssignable bool `json:"auto_assignable"`
|
||||||
|
|
||||||
// Client type
|
// Client type
|
||||||
ClientType string `json:"clientType"`
|
ClientType string `json:"clientType"`
|
||||||
|
|
||||||
// Description
|
// Description
|
||||||
Description string `json:"desc"`
|
Description string `json:"desc"`
|
||||||
|
|
||||||
|
// Domain name
|
||||||
|
DomainName string `json:"domainname"`
|
||||||
|
|
||||||
|
// Hostname
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
|
||||||
// IP
|
// IP
|
||||||
IP string `json:"ip"`
|
IP string `json:"ip"`
|
||||||
|
|
||||||
@@ -37,12 +46,6 @@ type ItemReservation struct {
|
|||||||
|
|
||||||
// Virtual machine ID
|
// Virtual machine ID
|
||||||
VMID uint64 `json:"vmId"`
|
VMID uint64 `json:"vmId"`
|
||||||
|
|
||||||
// Domain name
|
|
||||||
DomainName string `json:"domainname"`
|
|
||||||
|
|
||||||
// Hostname
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List reservations
|
// List reservations
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ type RecordGrid struct {
|
|||||||
|
|
||||||
// Budget
|
// Budget
|
||||||
Budget bool `json:"budget"`
|
Budget bool `json:"budget"`
|
||||||
|
|
||||||
|
// Whether VM folders are enabled
|
||||||
|
VMFoldersEnabled bool `json:"vm_folders_enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information about grid
|
// Information about grid
|
||||||
@@ -165,6 +168,9 @@ type ItemGridList struct {
|
|||||||
|
|
||||||
// Budget
|
// Budget
|
||||||
Budget bool `json:"budget"`
|
Budget bool `json:"budget"`
|
||||||
|
|
||||||
|
// Whether VM folders are enabled
|
||||||
|
VMFoldersEnabled bool `json:"vm_folders_enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List Grids
|
// List Grids
|
||||||
|
|||||||
@@ -240,6 +240,10 @@ type CreateRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
||||||
|
|
||||||
|
// List of PCI device IDs to attach to this VM
|
||||||
|
// Required: false
|
||||||
|
PCIdevices []uint64 `url:"pcidevices,omitempty" json:"pcidevices,omitempty"`
|
||||||
|
|
||||||
// Zone ID
|
// Zone ID
|
||||||
// Required: false
|
// Required: false
|
||||||
ZoneID uint64 `url:"zoneId,omitempty" json:"zoneId,omitempty"`
|
ZoneID uint64 `url:"zoneId,omitempty" json:"zoneId,omitempty"`
|
||||||
@@ -275,6 +279,10 @@ type CreateRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
// Default: "auto"
|
// Default: "auto"
|
||||||
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
||||||
|
|
||||||
|
// List of vGPU IDs to attach to the VM
|
||||||
|
// Required: false
|
||||||
|
VGPUs []uint64 `url:"vgpus,omitempty" json:"vgpus,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRAM returns RAM field values
|
// GetRAM returns RAM field values
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ type CreateBlankRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
PreferredCPU []int64 `url:"preferredCpu,omitempty" json:"preferredCpu,omitempty" validate:"omitempty,preferredCPU"`
|
||||||
|
|
||||||
|
// List of PCI device IDs to attach to this VM
|
||||||
|
// Required: false
|
||||||
|
PCIdevices []uint64 `url:"pcidevices,omitempty" json:"pcidevices,omitempty"`
|
||||||
|
|
||||||
// VM type linux, windows or unknown
|
// VM type linux, windows or unknown
|
||||||
// Required: false
|
// Required: false
|
||||||
LoaderType string `url:"loaderType,omitempty" json:"loaderType,omitempty" validate:"omitempty,loaderType"`
|
LoaderType string `url:"loaderType,omitempty" json:"loaderType,omitempty" validate:"omitempty,loaderType"`
|
||||||
@@ -147,6 +151,10 @@ type CreateBlankRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
// Default: "auto"
|
// Default: "auto"
|
||||||
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
MemoryBalloonMode string `url:"memory_balloon_mode,omitempty" json:"memory_balloon_mode,omitempty" validate:"omitempty,memoryBalloonMode"`
|
||||||
|
|
||||||
|
// List of vGPU IDs to attach to the VM
|
||||||
|
// Required: false
|
||||||
|
VGPUs []uint64 `url:"vgpus,omitempty" json:"vgpus,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRAM returns RAM field values
|
// GetRAM returns RAM field values
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func TestMigrator(t *testing.T) {
|
|||||||
ComputeID: dxVMID,
|
ComputeID: dxVMID,
|
||||||
TargetNodeID: nodeID,
|
TargetNodeID: nodeID,
|
||||||
},
|
},
|
||||||
SyncMode: true})).Return(b, nil).AnyTimes()
|
AsyncMode: false})).Return(b, nil).AnyTimes()
|
||||||
|
|
||||||
ok, err := migrator.Migrate(context.Background(), dxVMID, nodeID)
|
ok, err := migrator.Migrate(context.Background(), dxVMID, nodeID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -87,8 +87,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
|
|
||||||
getResult("Account list", bytes, account.ListAccounts{}, t)
|
getResult("Account list", bytes, account.ListAccounts{}, t)
|
||||||
// Get
|
// Get
|
||||||
listAcc, _ := client.CloudAPI().Account().List(context.Background(), account.ListRequest{})
|
listAcc, err := client.CloudAPI().Account().List(context.Background(), account.ListRequest{})
|
||||||
if len(listAcc.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Account.List failed: %v", err)
|
||||||
|
} else if len(listAcc.Data) > 0 {
|
||||||
id := listAcc.Data[0].ID
|
id := listAcc.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().Account().GetRaw(context.Background(), account.GetRequest{AccountID: id})
|
bytes, err = client.CloudAPI().Account().GetRaw(context.Background(), account.GetRequest{AccountID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -107,8 +109,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Audit list", bytes, audit.ListAudits{}, t)
|
getResult("Audit list", bytes, audit.ListAudits{}, t)
|
||||||
// Get
|
// Get
|
||||||
listAudits, _ := client.CloudAPI().Audit().List(context.Background(), audit.ListRequest{})
|
listAudits, err := client.CloudAPI().Audit().List(context.Background(), audit.ListRequest{})
|
||||||
if len(listAudits.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Audit.List failed: %v", err)
|
||||||
|
} else if len(listAudits.Data) > 0 {
|
||||||
id := listAudits.Data[0].GUID
|
id := listAudits.Data[0].GUID
|
||||||
bytes, err = client.CloudAPI().Audit().GetRaw(context.Background(), audit.GetRequest{AuditGuid: id})
|
bytes, err = client.CloudAPI().Audit().GetRaw(context.Background(), audit.GetRequest{AuditGuid: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -127,8 +131,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Bservice list", bytes, bservice.ListBasicServices{}, t)
|
getResult("Bservice list", bytes, bservice.ListBasicServices{}, t)
|
||||||
// Get
|
// Get
|
||||||
listBServ, _ := client.CloudAPI().BService().List(context.Background(), bservice.ListRequest{})
|
listBServ, err := client.CloudAPI().BService().List(context.Background(), bservice.ListRequest{})
|
||||||
if len(listBServ.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.BService.List failed: %v", err)
|
||||||
|
} else if len(listBServ.Data) > 0 {
|
||||||
id := listBServ.Data[0].ID
|
id := listBServ.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().BService().GetRaw(context.Background(), bservice.GetRequest{ServiceID: id})
|
bytes, err = client.CloudAPI().BService().GetRaw(context.Background(), bservice.GetRequest{ServiceID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -147,8 +153,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Compute list", bytes, compute.ListComputes{}, t)
|
getResult("Compute list", bytes, compute.ListComputes{}, t)
|
||||||
// Get
|
// Get
|
||||||
listComp, _ := client.CloudAPI().Compute().List(context.Background(), compute.ListRequest{})
|
listComp, err := client.CloudAPI().Compute().List(context.Background(), compute.ListRequest{})
|
||||||
if listComp != nil && len(listComp.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Compute.List failed: %v", err)
|
||||||
|
} else if listComp != nil && len(listComp.Data) > 0 {
|
||||||
id := listComp.Data[0].ID
|
id := listComp.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().Compute().GetRaw(context.Background(), compute.GetRequest{ComputeID: id})
|
bytes, err = client.CloudAPI().Compute().GetRaw(context.Background(), compute.GetRequest{ComputeID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -173,8 +181,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Disk list", bytes, disks.ListDisks{}, t)
|
getResult("Disk list", bytes, disks.ListDisks{}, t)
|
||||||
// Get
|
// Get
|
||||||
listDisk, _ := client.CloudAPI().Disks().List(context.Background(), disks.ListRequest{})
|
listDisk, err := client.CloudAPI().Disks().List(context.Background(), disks.ListRequest{})
|
||||||
if len(listDisk.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Disks.List failed: %v", err)
|
||||||
|
} else if len(listDisk.Data) > 0 {
|
||||||
id := listDisk.Data[0].ID
|
id := listDisk.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().Disks().GetRaw(context.Background(), disks.GetRequest{DiskID: id})
|
bytes, err = client.CloudAPI().Disks().GetRaw(context.Background(), disks.GetRequest{DiskID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -193,8 +203,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("ExtNet list", bytes, extnet.ListExtNets{}, t)
|
getResult("ExtNet list", bytes, extnet.ListExtNets{}, t)
|
||||||
// Get
|
// Get
|
||||||
listExtNet, _ := client.CloudAPI().ExtNet().List(context.Background(), extnet.ListRequest{})
|
listExtNet, err := client.CloudAPI().ExtNet().List(context.Background(), extnet.ListRequest{})
|
||||||
if len(listExtNet.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.ExtNet.List failed: %v", err)
|
||||||
|
} else if len(listExtNet.Data) > 0 {
|
||||||
id := listExtNet.Data[0].ID
|
id := listExtNet.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().ExtNet().GetRaw(context.Background(), extnet.GetRequest{NetID: id})
|
bytes, err = client.CloudAPI().ExtNet().GetRaw(context.Background(), extnet.GetRequest{NetID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -213,8 +225,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("FLIPGroup list", bytes, flipgroup.ListFLIPGroups{}, t)
|
getResult("FLIPGroup list", bytes, flipgroup.ListFLIPGroups{}, t)
|
||||||
// Get
|
// Get
|
||||||
listFG, _ := client.CloudAPI().FLIPGroup().List(context.Background(), flipgroup.ListRequest{})
|
listFG, err := client.CloudAPI().FLIPGroup().List(context.Background(), flipgroup.ListRequest{})
|
||||||
if len(listFG.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.FLIPGroup.List failed: %v", err)
|
||||||
|
} else if len(listFG.Data) > 0 {
|
||||||
id := listFG.Data[0].ID
|
id := listFG.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().FLIPGroup().GetRaw(context.Background(), flipgroup.GetRequest{FLIPGroupID: id})
|
bytes, err = client.CloudAPI().FLIPGroup().GetRaw(context.Background(), flipgroup.GetRequest{FLIPGroupID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -233,8 +247,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Image list", bytes, image.ListImages{}, t)
|
getResult("Image list", bytes, image.ListImages{}, t)
|
||||||
// Get
|
// Get
|
||||||
listImg, _ := client.CloudAPI().Image().List(context.Background(), image.ListRequest{})
|
listImg, err := client.CloudAPI().Image().List(context.Background(), image.ListRequest{})
|
||||||
if len(listImg.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Image.List failed: %v", err)
|
||||||
|
} else if len(listImg.Data) > 0 {
|
||||||
id := listImg.Data[0].ID
|
id := listImg.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().Image().GetRaw(context.Background(), image.GetRequest{ImageID: id})
|
bytes, err = client.CloudAPI().Image().GetRaw(context.Background(), image.GetRequest{ImageID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -253,8 +269,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("K8CI list", bytes, k8ci.ListK8CI{}, t)
|
getResult("K8CI list", bytes, k8ci.ListK8CI{}, t)
|
||||||
// Get
|
// Get
|
||||||
listk8ci, _ := client.CloudAPI().K8CI().List(context.Background(), k8ci.ListRequest{})
|
listk8ci, err := client.CloudAPI().K8CI().List(context.Background(), k8ci.ListRequest{})
|
||||||
if len(listk8ci.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.K8CI.List failed: %v", err)
|
||||||
|
} else if len(listk8ci.Data) > 0 {
|
||||||
id := listk8ci.Data[0].ID
|
id := listk8ci.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().K8CI().GetRaw(context.Background(), k8ci.GetRequest{K8CIID: id})
|
bytes, err = client.CloudAPI().K8CI().GetRaw(context.Background(), k8ci.GetRequest{K8CIID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -273,8 +291,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("K8S list", bytes, k8s.ListK8SClusters{}, t)
|
getResult("K8S list", bytes, k8s.ListK8SClusters{}, t)
|
||||||
// Get
|
// Get
|
||||||
listk8s, _ := client.CloudAPI().K8S().List(context.Background(), k8s.ListRequest{})
|
listk8s, err := client.CloudAPI().K8S().List(context.Background(), k8s.ListRequest{})
|
||||||
if len(listk8s.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.K8S.List failed: %v", err)
|
||||||
|
} else if len(listk8s.Data) > 0 {
|
||||||
id := listk8s.Data[0].ID
|
id := listk8s.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().K8S().GetRaw(context.Background(), k8s.GetRequest{K8SID: id})
|
bytes, err = client.CloudAPI().K8S().GetRaw(context.Background(), k8s.GetRequest{K8SID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -293,8 +313,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("LB list", bytes, lb.ListLB{}, t)
|
getResult("LB list", bytes, lb.ListLB{}, t)
|
||||||
// Get
|
// Get
|
||||||
listLB, _ := client.CloudAPI().LB().List(context.Background(), lb.ListRequest{})
|
listLB, err := client.CloudAPI().LB().List(context.Background(), lb.ListRequest{})
|
||||||
if len(listLB.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.LB.List failed: %v", err)
|
||||||
|
} else if len(listLB.Data) > 0 {
|
||||||
id := listLB.Data[0].ID
|
id := listLB.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().LB().GetRaw(context.Background(), lb.GetRequest{LBID: id})
|
bytes, err = client.CloudAPI().LB().GetRaw(context.Background(), lb.GetRequest{LBID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -321,8 +343,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("QoS policy list", bytes, qospolicy.ListQoSPolicies{}, t)
|
getResult("QoS policy list", bytes, qospolicy.ListQoSPolicies{}, t)
|
||||||
// Get
|
// Get
|
||||||
listQosPolicies, _ := client.CloudAPI().QoSPolicy().List(context.Background(), qospolicy.ListRequest{})
|
listQosPolicies, err := client.CloudAPI().QoSPolicy().List(context.Background(), qospolicy.ListRequest{})
|
||||||
if len(listQosPolicies.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.QoSPolicy.List failed: %v", err)
|
||||||
|
} else if len(listQosPolicies.Data) > 0 {
|
||||||
id := listQosPolicies.Data[0].ID
|
id := listQosPolicies.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().QoSPolicy().GetRaw(context.Background(), qospolicy.GetRequest{QoSPolicyID: id})
|
bytes, err = client.CloudAPI().QoSPolicy().GetRaw(context.Background(), qospolicy.GetRequest{QoSPolicyID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -341,8 +365,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("RG list", bytes, rg.ListResourceGroups{}, t)
|
getResult("RG list", bytes, rg.ListResourceGroups{}, t)
|
||||||
// Get
|
// Get
|
||||||
listRG, _ := client.CloudAPI().RG().List(context.Background(), rg.ListRequest{})
|
listRG, err := client.CloudAPI().RG().List(context.Background(), rg.ListRequest{})
|
||||||
if len(listRG.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.RG.List failed: %v", err)
|
||||||
|
} else if len(listRG.Data) > 0 {
|
||||||
id := listRG.Data[0].ID
|
id := listRG.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().RG().GetRaw(context.Background(), rg.GetRequest{RGID: id})
|
bytes, err = client.CloudAPI().RG().GetRaw(context.Background(), rg.GetRequest{RGID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -369,8 +395,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Storage policy list", bytes, stpolicy.ListStoragePolicies{}, t)
|
getResult("Storage policy list", bytes, stpolicy.ListStoragePolicies{}, t)
|
||||||
// Get
|
// Get
|
||||||
listStoragePolicies, _ := client.CloudAPI().StPolicy().List(context.Background(), stpolicy.ListRequest{})
|
listStoragePolicies, err := client.CloudAPI().StPolicy().List(context.Background(), stpolicy.ListRequest{})
|
||||||
if len(listStoragePolicies.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.StPolicy.List failed: %v", err)
|
||||||
|
} else if len(listStoragePolicies.Data) > 0 {
|
||||||
id := listStoragePolicies.Data[0].ID
|
id := listStoragePolicies.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().StPolicy().GetRaw(context.Background(), stpolicy.GetRequest{StoragePolicyID: id})
|
bytes, err = client.CloudAPI().StPolicy().GetRaw(context.Background(), stpolicy.GetRequest{StoragePolicyID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -389,8 +417,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Replication profile list", bytes, stpolicy.ListReplicationProfiles{}, t)
|
getResult("Replication profile list", bytes, stpolicy.ListReplicationProfiles{}, t)
|
||||||
// Get
|
// Get
|
||||||
listReplicationProfiles, _ := client.CloudAPI().StPolicy().ListReplicationProfile(context.Background(), stpolicy.ListReplicationProfileRequest{})
|
listReplicationProfiles, err := client.CloudAPI().StPolicy().ListReplicationProfile(context.Background(), stpolicy.ListReplicationProfileRequest{})
|
||||||
if len(listReplicationProfiles.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.StPolicy.ListReplicationProfile failed: %v", err)
|
||||||
|
} else if len(listReplicationProfiles.Data) > 0 {
|
||||||
id := listReplicationProfiles.Data[0].ID
|
id := listReplicationProfiles.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().StPolicy().GetReplicationProfileRaw(context.Background(), stpolicy.GetReplicationProfileRequest{ProfileID: id})
|
bytes, err = client.CloudAPI().StPolicy().GetReplicationProfileRaw(context.Background(), stpolicy.GetReplicationProfileRequest{ProfileID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -409,8 +439,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Security group list", bytes, secgroup.ListSecurityGroups{}, t)
|
getResult("Security group list", bytes, secgroup.ListSecurityGroups{}, t)
|
||||||
// Get
|
// Get
|
||||||
listSecurityGroups, _ := client.CloudAPI().SecurityGroup().List(context.Background(), secgroup.ListRequest{})
|
listSecurityGroups, err := client.CloudAPI().SecurityGroup().List(context.Background(), secgroup.ListRequest{})
|
||||||
if len(listSecurityGroups.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.SecurityGroup.List failed: %v", err)
|
||||||
|
} else if len(listSecurityGroups.Data) > 0 {
|
||||||
id := listSecurityGroups.Data[0].ID
|
id := listSecurityGroups.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().SecurityGroup().GetRaw(context.Background(), secgroup.GetRequest{SecurityGroupID: id})
|
bytes, err = client.CloudAPI().SecurityGroup().GetRaw(context.Background(), secgroup.GetRequest{SecurityGroupID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -429,8 +461,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Tasks list", bytes, tasks.ListTasks{}, t)
|
getResult("Tasks list", bytes, tasks.ListTasks{}, t)
|
||||||
// Get
|
// Get
|
||||||
listTasks, _ := client.CloudAPI().Tasks().List(context.Background(), tasks.ListRequest{})
|
listTasks, err := client.CloudAPI().Tasks().List(context.Background(), tasks.ListRequest{})
|
||||||
if len(listTasks.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Tasks.List failed: %v", err)
|
||||||
|
} else if len(listTasks.Data) > 0 {
|
||||||
id := listTasks.Data[0].AuditID
|
id := listTasks.Data[0].AuditID
|
||||||
bytes, err = client.CloudAPI().Tasks().GetRaw(context.Background(), tasks.GetRequest{AuditID: id})
|
bytes, err = client.CloudAPI().Tasks().GetRaw(context.Background(), tasks.GetRequest{AuditID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -449,8 +483,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Trunk list", bytes, trunk.ListTrunks{}, t)
|
getResult("Trunk list", bytes, trunk.ListTrunks{}, t)
|
||||||
// Get
|
// Get
|
||||||
listTrunk, _ := client.CloudAPI().Trunk().List(context.Background(), trunk.ListRequest{})
|
listTrunk, err := client.CloudAPI().Trunk().List(context.Background(), trunk.ListRequest{})
|
||||||
if len(listTrunk.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Trunk.List failed: %v", err)
|
||||||
|
} else if len(listTrunk.Data) > 0 {
|
||||||
id := listTrunk.Data[0].ID
|
id := listTrunk.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().Trunk().GetRaw(context.Background(), trunk.GetRequest{TrunkID: id})
|
bytes, err = client.CloudAPI().Trunk().GetRaw(context.Background(), trunk.GetRequest{TrunkID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -469,8 +505,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("VINS list", bytes, vins.ListVINS{}, t)
|
getResult("VINS list", bytes, vins.ListVINS{}, t)
|
||||||
// Get
|
// Get
|
||||||
listVINS, _ := client.CloudAPI().VINS().List(context.Background(), vins.ListRequest{})
|
listVINS, err := client.CloudAPI().VINS().List(context.Background(), vins.ListRequest{})
|
||||||
if len(listVINS.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.VINS.List failed: %v", err)
|
||||||
|
} else if len(listVINS.Data) > 0 {
|
||||||
id := listVINS.Data[0].ID
|
id := listVINS.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().VINS().GetRaw(context.Background(), vins.GetRequest{VINSID: id})
|
bytes, err = client.CloudAPI().VINS().GetRaw(context.Background(), vins.GetRequest{VINSID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -481,24 +519,31 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
t.Errorf("Can not test VINS get because VINS list is empty")
|
t.Errorf("Can not test VINS get because VINS list is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// VM folder
|
// VM folder (list requires rg_id)
|
||||||
// List
|
if listRG == nil || len(listRG.Data) == 0 {
|
||||||
bytes, err = client.CloudAPI().VMFolder().ListRaw(context.Background(), vmfolder.ListRequest{})
|
t.Errorf("Can not test VM folder because VM folder list is empty")
|
||||||
if err != nil {
|
} else {
|
||||||
t.Error(err)
|
rgID := listRG.Data[0].ID
|
||||||
}
|
// List
|
||||||
getResult("VM folder list", bytes, vmfolder.ListVMFolder{}, t)
|
bytes, err = client.CloudAPI().VMFolder().ListRaw(context.Background(), vmfolder.ListRequest{RGID: rgID})
|
||||||
// Get
|
|
||||||
listVMFolders, _ := client.CloudAPI().VMFolder().List(context.Background(), vmfolder.ListRequest{})
|
|
||||||
if len(listVMFolders.Data) > 0 {
|
|
||||||
id := listVMFolders.Data[0].ID
|
|
||||||
bytes, err = client.CloudAPI().VMFolder().GetRaw(context.Background(), vmfolder.GetRequest{FolderID: id})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
getResult("VM folder get", bytes, vmfolder.RecordVMFolder{}, t)
|
getResult("VM folder list", bytes, vmfolder.ListVMFolder{}, t)
|
||||||
} else {
|
// Get
|
||||||
t.Errorf("Can not test VM folder get because VM folder list is empty")
|
listVMFolders, err := client.CloudAPI().VMFolder().List(context.Background(), vmfolder.ListRequest{RGID: rgID})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.VMFolder.List failed: %v", err)
|
||||||
|
} else if len(listVMFolders.Data) > 0 {
|
||||||
|
id := listVMFolders.Data[0].ID
|
||||||
|
bytes, err = client.CloudAPI().VMFolder().GetRaw(context.Background(), vmfolder.GetRequest{FolderID: id})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
getResult("VM folder get", bytes, vmfolder.RecordVMFolder{}, t)
|
||||||
|
} else {
|
||||||
|
t.Errorf("Can not test VM folder get because VM folder list is empty")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VGPU
|
// VGPU
|
||||||
@@ -517,8 +562,10 @@ func TestGetListCloudAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Zone list", bytes, zone.ListZones{}, t)
|
getResult("Zone list", bytes, zone.ListZones{}, t)
|
||||||
// Get
|
// Get
|
||||||
ListZones, _ := client.CloudAPI().Zone().List(context.Background(), zone.ListRequest{})
|
ListZones, err := client.CloudAPI().Zone().List(context.Background(), zone.ListRequest{})
|
||||||
if len(ListZones.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudAPI.Zone.List failed: %v", err)
|
||||||
|
} else if len(ListZones.Data) > 0 {
|
||||||
id := ListZones.Data[0].ID
|
id := ListZones.Data[0].ID
|
||||||
bytes, err = client.CloudAPI().Zone().GetRaw(context.Background(), zone.GetRequest{ID: id})
|
bytes, err = client.CloudAPI().Zone().GetRaw(context.Background(), zone.GetRequest{ID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -549,8 +596,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Account list", bytes, account_cb.ListAccounts{}, t)
|
getResult("Account list", bytes, account_cb.ListAccounts{}, t)
|
||||||
// Get
|
// Get
|
||||||
listAcc, _ := client.CloudBroker().Account().List(context.Background(), account_cb.ListRequest{})
|
listAcc, err := client.CloudBroker().Account().List(context.Background(), account_cb.ListRequest{})
|
||||||
if len(listAcc.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Account.List failed: %v", err)
|
||||||
|
} else if len(listAcc.Data) > 0 {
|
||||||
id := listAcc.Data[0].ID
|
id := listAcc.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Account().GetRaw(context.Background(), account_cb.GetRequest{AccountID: id})
|
bytes, err = client.CloudBroker().Account().GetRaw(context.Background(), account_cb.GetRequest{AccountID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -569,8 +618,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Audit list", bytes, audit_cb.ListAudits{}, t)
|
getResult("Audit list", bytes, audit_cb.ListAudits{}, t)
|
||||||
// Get
|
// Get
|
||||||
listAudits, _ := client.CloudBroker().Audit().List(context.Background(), audit_cb.ListRequest{})
|
listAudits, err := client.CloudBroker().Audit().List(context.Background(), audit_cb.ListRequest{})
|
||||||
if len(listAudits.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Audit.List failed: %v", err)
|
||||||
|
} else if len(listAudits.Data) > 0 {
|
||||||
id := listAudits.Data[0].GUID
|
id := listAudits.Data[0].GUID
|
||||||
bytes, err = client.CloudBroker().Audit().GetRaw(context.Background(), audit_cb.GetRequest{AuditGuid: id})
|
bytes, err = client.CloudBroker().Audit().GetRaw(context.Background(), audit_cb.GetRequest{AuditGuid: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -589,8 +640,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Bservice list", bytes, bservice_cb.ListBasicServices{}, t)
|
getResult("Bservice list", bytes, bservice_cb.ListBasicServices{}, t)
|
||||||
// Get
|
// Get
|
||||||
listBServ, _ := client.CloudBroker().BService().List(context.Background(), bservice_cb.ListRequest{})
|
listBServ, err := client.CloudBroker().BService().List(context.Background(), bservice_cb.ListRequest{})
|
||||||
if len(listBServ.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.BService.List failed: %v", err)
|
||||||
|
} else if len(listBServ.Data) > 0 {
|
||||||
id := listBServ.Data[0].ID
|
id := listBServ.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().BService().GetRaw(context.Background(), bservice_cb.GetRequest{ServiceID: id})
|
bytes, err = client.CloudBroker().BService().GetRaw(context.Background(), bservice_cb.GetRequest{ServiceID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -609,8 +662,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Compute list", bytes, compute_cb.ListComputes{}, t)
|
getResult("Compute list", bytes, compute_cb.ListComputes{}, t)
|
||||||
// Get
|
// Get
|
||||||
listComp, _ := client.CloudBroker().Compute().List(context.Background(), compute_cb.ListRequest{})
|
listComp, err := client.CloudBroker().Compute().List(context.Background(), compute_cb.ListRequest{})
|
||||||
if len(listComp.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Compute.List failed: %v", err)
|
||||||
|
} else if len(listComp.Data) > 0 {
|
||||||
id := listComp.Data[0].ID
|
id := listComp.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Compute().GetRaw(context.Background(), compute_cb.GetRequest{ComputeID: id})
|
bytes, err = client.CloudBroker().Compute().GetRaw(context.Background(), compute_cb.GetRequest{ComputeID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -635,8 +690,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Disk list", bytes, disks_cb.ListDisks{}, t)
|
getResult("Disk list", bytes, disks_cb.ListDisks{}, t)
|
||||||
// Get
|
// Get
|
||||||
listDisk, _ := client.CloudBroker().Disks().List(context.Background(), disks_cb.ListRequest{})
|
listDisk, err := client.CloudBroker().Disks().List(context.Background(), disks_cb.ListRequest{})
|
||||||
if len(listDisk.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Disks.List failed: %v", err)
|
||||||
|
} else if len(listDisk.Data) > 0 {
|
||||||
id := listDisk.Data[0].ID
|
id := listDisk.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Disks().GetRaw(context.Background(), disks_cb.GetRequest{DiskID: id})
|
bytes, err = client.CloudBroker().Disks().GetRaw(context.Background(), disks_cb.GetRequest{DiskID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -655,8 +712,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("ExtNet list", bytes, extnet_cb.ListExtNet{}, t)
|
getResult("ExtNet list", bytes, extnet_cb.ListExtNet{}, t)
|
||||||
// Get
|
// Get
|
||||||
listExtNet, _ := client.CloudBroker().ExtNet().List(context.Background(), extnet_cb.ListRequest{})
|
listExtNet, err := client.CloudBroker().ExtNet().List(context.Background(), extnet_cb.ListRequest{})
|
||||||
if len(listExtNet.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.ExtNet.List failed: %v", err)
|
||||||
|
} else if len(listExtNet.Data) > 0 {
|
||||||
id := listExtNet.Data[0].ID
|
id := listExtNet.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().ExtNet().GetRaw(context.Background(), extnet_cb.GetRequest{NetID: id})
|
bytes, err = client.CloudBroker().ExtNet().GetRaw(context.Background(), extnet_cb.GetRequest{NetID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -675,8 +734,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("FLIPGroup list", bytes, flipgroup_cb.ListFLIPGroups{}, t)
|
getResult("FLIPGroup list", bytes, flipgroup_cb.ListFLIPGroups{}, t)
|
||||||
// Get
|
// Get
|
||||||
listFG, _ := client.CloudBroker().FLIPGroup().List(context.Background(), flipgroup_cb.ListRequest{})
|
listFG, err := client.CloudBroker().FLIPGroup().List(context.Background(), flipgroup_cb.ListRequest{})
|
||||||
if len(listFG.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.FLIPGroup.List failed: %v", err)
|
||||||
|
} else if len(listFG.Data) > 0 {
|
||||||
id := listFG.Data[0].ID
|
id := listFG.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().FLIPGroup().GetRaw(context.Background(), flipgroup_cb.GetRequest{FLIPGroupID: id})
|
bytes, err = client.CloudBroker().FLIPGroup().GetRaw(context.Background(), flipgroup_cb.GetRequest{FLIPGroupID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -695,8 +756,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Grid list", bytes, grid_cb.ListGrids{}, t)
|
getResult("Grid list", bytes, grid_cb.ListGrids{}, t)
|
||||||
// Get
|
// Get
|
||||||
listGrid, _ := client.CloudBroker().Grid().List(context.Background(), grid_cb.ListRequest{})
|
listGrid, err := client.CloudBroker().Grid().List(context.Background(), grid_cb.ListRequest{})
|
||||||
if len(listGrid.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Grid.List failed: %v", err)
|
||||||
|
} else if len(listGrid.Data) > 0 {
|
||||||
id := listGrid.Data[0].ID
|
id := listGrid.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Grid().GetRaw(context.Background(), grid_cb.GetRequest{GID: id})
|
bytes, err = client.CloudBroker().Grid().GetRaw(context.Background(), grid_cb.GetRequest{GID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -715,8 +778,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Image list", bytes, image_cb.ListImages{}, t)
|
getResult("Image list", bytes, image_cb.ListImages{}, t)
|
||||||
// Get
|
// Get
|
||||||
listImg, _ := client.CloudBroker().Image().List(context.Background(), image_cb.ListRequest{})
|
listImg, err := client.CloudBroker().Image().List(context.Background(), image_cb.ListRequest{})
|
||||||
if len(listImg.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Image.List failed: %v", err)
|
||||||
|
} else if len(listImg.Data) > 0 {
|
||||||
id := listImg.Data[0].ID
|
id := listImg.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Image().GetRaw(context.Background(), image_cb.GetRequest{ImageID: id})
|
bytes, err = client.CloudBroker().Image().GetRaw(context.Background(), image_cb.GetRequest{ImageID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -735,8 +800,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("K8CI list", bytes, k8ci_cb.ListK8CI{}, t)
|
getResult("K8CI list", bytes, k8ci_cb.ListK8CI{}, t)
|
||||||
// Get
|
// Get
|
||||||
listk8ci, _ := client.CloudBroker().K8CI().List(context.Background(), k8ci_cb.ListRequest{})
|
listk8ci, err := client.CloudBroker().K8CI().List(context.Background(), k8ci_cb.ListRequest{})
|
||||||
if len(listk8ci.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.K8CI.List failed: %v", err)
|
||||||
|
} else if len(listk8ci.Data) > 0 {
|
||||||
id := listk8ci.Data[0].ID
|
id := listk8ci.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().K8CI().GetRaw(context.Background(), k8ci_cb.GetRequest{K8CIID: id})
|
bytes, err = client.CloudBroker().K8CI().GetRaw(context.Background(), k8ci_cb.GetRequest{K8CIID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -755,8 +822,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("K8S list", bytes, k8s_cb.ListK8S{}, t)
|
getResult("K8S list", bytes, k8s_cb.ListK8S{}, t)
|
||||||
// Get
|
// Get
|
||||||
listk8s, _ := client.CloudBroker().K8S().List(context.Background(), k8s_cb.ListRequest{})
|
listk8s, err := client.CloudBroker().K8S().List(context.Background(), k8s_cb.ListRequest{})
|
||||||
if len(listk8s.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.K8S.List failed: %v", err)
|
||||||
|
} else if len(listk8s.Data) > 0 {
|
||||||
id := listk8s.Data[0].ID
|
id := listk8s.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().K8S().GetRaw(context.Background(), k8s_cb.GetRequest{K8SID: id})
|
bytes, err = client.CloudBroker().K8S().GetRaw(context.Background(), k8s_cb.GetRequest{K8SID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -775,8 +844,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("LB list", bytes, lb_cb.ListLB{}, t)
|
getResult("LB list", bytes, lb_cb.ListLB{}, t)
|
||||||
// Get
|
// Get
|
||||||
listLB, _ := client.CloudBroker().LB().List(context.Background(), lb_cb.ListRequest{})
|
listLB, err := client.CloudBroker().LB().List(context.Background(), lb_cb.ListRequest{})
|
||||||
if len(listLB.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.LB.List failed: %v", err)
|
||||||
|
} else if len(listLB.Data) > 0 {
|
||||||
id := listLB.Data[0].ID
|
id := listLB.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().LB().GetRaw(context.Background(), lb_cb.GetRequest{LBID: id})
|
bytes, err = client.CloudBroker().LB().GetRaw(context.Background(), lb_cb.GetRequest{LBID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -795,8 +866,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Node list", bytes, node_cb.ListNodes{}, t)
|
getResult("Node list", bytes, node_cb.ListNodes{}, t)
|
||||||
// Get
|
// Get
|
||||||
listNode, _ := client.CloudBroker().Node().List(context.Background(), node_cb.ListRequest{})
|
listNode, err := client.CloudBroker().Node().List(context.Background(), node_cb.ListRequest{})
|
||||||
if listNode != nil && len(listNode.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Node.List failed: %v", err)
|
||||||
|
} else if listNode != nil && len(listNode.Data) > 0 {
|
||||||
id := listNode.Data[0].ID
|
id := listNode.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Node().GetRaw(context.Background(), node_cb.GetRequest{NID: id})
|
bytes, err = client.CloudBroker().Node().GetRaw(context.Background(), node_cb.GetRequest{NID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -841,8 +914,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("QoS policy list", bytes, qospolicy_cb.ListQoSPolicies{}, t)
|
getResult("QoS policy list", bytes, qospolicy_cb.ListQoSPolicies{}, t)
|
||||||
// Get
|
// Get
|
||||||
listQosPolicies, _ := client.CloudBroker().QoSPolicy().List(context.Background(), qospolicy_cb.ListRequest{})
|
listQosPolicies, err := client.CloudBroker().QoSPolicy().List(context.Background(), qospolicy_cb.ListRequest{})
|
||||||
if len(listQosPolicies.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.QoSPolicy.List failed: %v", err)
|
||||||
|
} else if len(listQosPolicies.Data) > 0 {
|
||||||
id := listQosPolicies.Data[0].ID
|
id := listQosPolicies.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().QoSPolicy().GetRaw(context.Background(), qospolicy_cb.GetRequest{QoSPolicyID: id})
|
bytes, err = client.CloudBroker().QoSPolicy().GetRaw(context.Background(), qospolicy_cb.GetRequest{QoSPolicyID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -861,8 +936,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("RG list", bytes, rg_cb.ListRG{}, t)
|
getResult("RG list", bytes, rg_cb.ListRG{}, t)
|
||||||
// Get
|
// Get
|
||||||
listRG, _ := client.CloudBroker().RG().List(context.Background(), rg_cb.ListRequest{})
|
listRG, err := client.CloudBroker().RG().List(context.Background(), rg_cb.ListRequest{})
|
||||||
if len(listRG.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.RG.List failed: %v", err)
|
||||||
|
} else if len(listRG.Data) > 0 {
|
||||||
id := listRG.Data[0].ID
|
id := listRG.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().RG().GetRaw(context.Background(), rg_cb.GetRequest{RGID: id})
|
bytes, err = client.CloudBroker().RG().GetRaw(context.Background(), rg_cb.GetRequest{RGID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -881,8 +958,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Security group list", bytes, secgroup_cb.ListSecurityGroups{}, t)
|
getResult("Security group list", bytes, secgroup_cb.ListSecurityGroups{}, t)
|
||||||
// Get
|
// Get
|
||||||
listSecurityGroups, _ := client.CloudBroker().SecurityGroup().List(context.Background(), secgroup_cb.ListRequest{})
|
listSecurityGroups, err := client.CloudBroker().SecurityGroup().List(context.Background(), secgroup_cb.ListRequest{})
|
||||||
if len(listSecurityGroups.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.SecurityGroup.List failed: %v", err)
|
||||||
|
} else if len(listSecurityGroups.Data) > 0 {
|
||||||
id := listSecurityGroups.Data[0].ID
|
id := listSecurityGroups.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().SecurityGroup().GetRaw(context.Background(), secgroup_cb.GetRequest{SecurityGroupID: id})
|
bytes, err = client.CloudBroker().SecurityGroup().GetRaw(context.Background(), secgroup_cb.GetRequest{SecurityGroupID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -901,8 +980,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("SEP list", bytes, sep_cb.ListSEP{}, t)
|
getResult("SEP list", bytes, sep_cb.ListSEP{}, t)
|
||||||
// Get
|
// Get
|
||||||
listSEP, _ := client.CloudBroker().SEP().List(context.Background(), sep_cb.ListRequest{})
|
listSEP, err := client.CloudBroker().SEP().List(context.Background(), sep_cb.ListRequest{})
|
||||||
if len(listSEP.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.SEP.List failed: %v", err)
|
||||||
|
} else if len(listSEP.Data) > 0 {
|
||||||
id := listSEP.Data[0].ID
|
id := listSEP.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().SEP().GetRaw(context.Background(), sep_cb.GetRequest{SEPID: id})
|
bytes, err = client.CloudBroker().SEP().GetRaw(context.Background(), sep_cb.GetRequest{SEPID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -927,8 +1008,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Storage policy list", bytes, stpolicy_cb.ListStoragePolicies{}, t)
|
getResult("Storage policy list", bytes, stpolicy_cb.ListStoragePolicies{}, t)
|
||||||
// Get
|
// Get
|
||||||
listStoragePolicies, _ := client.CloudBroker().StPolicy().List(context.Background(), stpolicy_cb.ListRequest{})
|
listStoragePolicies, err := client.CloudBroker().StPolicy().List(context.Background(), stpolicy_cb.ListRequest{})
|
||||||
if len(listStoragePolicies.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.StPolicy.List failed: %v", err)
|
||||||
|
} else if len(listStoragePolicies.Data) > 0 {
|
||||||
id := listStoragePolicies.Data[0].ID
|
id := listStoragePolicies.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().StPolicy().GetRaw(context.Background(), stpolicy_cb.GetRequest{StoragePolicyID: id})
|
bytes, err = client.CloudBroker().StPolicy().GetRaw(context.Background(), stpolicy_cb.GetRequest{StoragePolicyID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -947,8 +1030,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Replication profile list", bytes, stpolicy_cb.ListReplicationProfiles{}, t)
|
getResult("Replication profile list", bytes, stpolicy_cb.ListReplicationProfiles{}, t)
|
||||||
// Get
|
// Get
|
||||||
listReplicationProfiles, _ := client.CloudBroker().StPolicy().ListReplicationProfile(context.Background(), stpolicy_cb.ListReplicationProfileRequest{})
|
listReplicationProfiles, err := client.CloudBroker().StPolicy().ListReplicationProfile(context.Background(), stpolicy_cb.ListReplicationProfileRequest{})
|
||||||
if len(listReplicationProfiles.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.StPolicy.ListReplicationProfile failed: %v", err)
|
||||||
|
} else if len(listReplicationProfiles.Data) > 0 {
|
||||||
id := listReplicationProfiles.Data[0].ID
|
id := listReplicationProfiles.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().StPolicy().GetReplicationProfileRaw(context.Background(), stpolicy_cb.GetReplicationProfileRequest{ProfileID: id})
|
bytes, err = client.CloudBroker().StPolicy().GetReplicationProfileRaw(context.Background(), stpolicy_cb.GetReplicationProfileRequest{ProfileID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -975,8 +1060,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Trunk list", bytes, trunk_cb.ListTrunks{}, t)
|
getResult("Trunk list", bytes, trunk_cb.ListTrunks{}, t)
|
||||||
// Get
|
// Get
|
||||||
listTrunks, _ := client.CloudBroker().Trunk().List(context.Background(), trunk_cb.ListRequest{})
|
listTrunks, err := client.CloudBroker().Trunk().List(context.Background(), trunk_cb.ListRequest{})
|
||||||
if len(listTrunks.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Trunk.List failed: %v", err)
|
||||||
|
} else if len(listTrunks.Data) > 0 {
|
||||||
id := listTrunks.Data[0].ID
|
id := listTrunks.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Trunk().GetRaw(context.Background(), trunk_cb.GetRequest{TrunkID: id})
|
bytes, err = client.CloudBroker().Trunk().GetRaw(context.Background(), trunk_cb.GetRequest{TrunkID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -995,8 +1082,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("VINS list", bytes, vins_cb.ListVINS{}, t)
|
getResult("VINS list", bytes, vins_cb.ListVINS{}, t)
|
||||||
// Get
|
// Get
|
||||||
listVINS, _ := client.CloudBroker().VINS().List(context.Background(), vins_cb.ListRequest{})
|
listVINS, err := client.CloudBroker().VINS().List(context.Background(), vins_cb.ListRequest{})
|
||||||
if len(listVINS.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.VINS.List failed: %v", err)
|
||||||
|
} else if len(listVINS.Data) > 0 {
|
||||||
id := listVINS.Data[0].ID
|
id := listVINS.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().VINS().GetRaw(context.Background(), vins_cb.GetRequest{VINSID: id})
|
bytes, err = client.CloudBroker().VINS().GetRaw(context.Background(), vins_cb.GetRequest{VINSID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1007,24 +1096,31 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
t.Errorf("Can not test VINS get because VINS list is empty")
|
t.Errorf("Can not test VINS get because VINS list is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// VM folder
|
// VM folder (list requires rg_id)
|
||||||
// List
|
if listRG == nil || len(listRG.Data) == 0 {
|
||||||
bytes, err = client.CloudBroker().VMFolder().ListRaw(context.Background(), vmfolder_cb.ListRequest{})
|
t.Errorf("Can not test VM folder because VM folder list is empty")
|
||||||
if err != nil {
|
} else {
|
||||||
t.Error(err)
|
rgID := listRG.Data[0].ID
|
||||||
}
|
// List
|
||||||
getResult("VM folder list", bytes, vmfolder_cb.ListVMFolder{}, t)
|
bytes, err = client.CloudBroker().VMFolder().ListRaw(context.Background(), vmfolder_cb.ListRequest{RGID: rgID})
|
||||||
// Get
|
|
||||||
listVMFolders, _ := client.CloudBroker().VMFolder().List(context.Background(), vmfolder_cb.ListRequest{})
|
|
||||||
if len(listVMFolders.Data) > 0 {
|
|
||||||
id := listVMFolders.Data[0].ID
|
|
||||||
bytes, err = client.CloudBroker().VMFolder().GetRaw(context.Background(), vmfolder_cb.GetRequest{FolderID: id})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
getResult("VM folder get", bytes, vmfolder_cb.RecordVMFolder{}, t)
|
getResult("VM folder list", bytes, vmfolder_cb.ListVMFolder{}, t)
|
||||||
} else {
|
// Get
|
||||||
t.Errorf("Can not test VM folder get because VM folder list is empty")
|
listVMFolders, err := client.CloudBroker().VMFolder().List(context.Background(), vmfolder_cb.ListRequest{RGID: rgID})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.VMFolder.List failed: %v", err)
|
||||||
|
} else if len(listVMFolders.Data) > 0 {
|
||||||
|
id := listVMFolders.Data[0].ID
|
||||||
|
bytes, err = client.CloudBroker().VMFolder().GetRaw(context.Background(), vmfolder_cb.GetRequest{FolderID: id})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
getResult("VM folder get", bytes, vmfolder_cb.RecordVMFolder{}, t)
|
||||||
|
} else {
|
||||||
|
t.Errorf("Can not test VM folder get because VM folder list is empty")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zone
|
// Zone
|
||||||
@@ -1035,8 +1131,10 @@ func TestGetListCloudbroker(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Zone list", bytes, zone.ListZones{}, t)
|
getResult("Zone list", bytes, zone.ListZones{}, t)
|
||||||
// Get
|
// Get
|
||||||
ListZones, _ := client.CloudBroker().Zone().List(context.Background(), zone_cb.ListRequest{})
|
ListZones, err := client.CloudBroker().Zone().List(context.Background(), zone_cb.ListRequest{})
|
||||||
if len(ListZones.Data) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because CloudBroker.Zone.List failed: %v", err)
|
||||||
|
} else if len(ListZones.Data) > 0 {
|
||||||
id := ListZones.Data[0].ID
|
id := ListZones.Data[0].ID
|
||||||
bytes, err = client.CloudBroker().Zone().GetRaw(context.Background(), zone_cb.GetRequest{ID: id})
|
bytes, err = client.CloudBroker().Zone().GetRaw(context.Background(), zone_cb.GetRequest{ID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1082,8 +1180,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
|
|
||||||
// Users AccessGroups
|
// Users AccessGroups
|
||||||
// list
|
// list
|
||||||
listGroups, _ := client.SDN().AccessGroups().List(context.Background(), acsgroups.ListGroupsRequest{})
|
listGroups, err := client.SDN().AccessGroups().List(context.Background(), acsgroups.ListGroupsRequest{})
|
||||||
if len(listGroups.AccessGroups) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.AccessGroups.List failed: %v", err)
|
||||||
|
} else if len(listGroups.AccessGroups) > 0 {
|
||||||
id := listGroups.AccessGroups[0].ID
|
id := listGroups.AccessGroups[0].ID
|
||||||
bytes, err = client.SDN().AccessGroups().UserListRaw(context.Background(), acsgroups.UsersListRequest{AccessGroupID: id})
|
bytes, err = client.SDN().AccessGroups().UserListRaw(context.Background(), acsgroups.UsersListRequest{AccessGroupID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1111,8 +1211,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Address pools list", bytes, adrspools.AddressPoolsList{}, t)
|
getResult("Address pools list", bytes, adrspools.AddressPoolsList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listStoragePolicies, _ := client.SDN().AddressPools().List(context.Background(), adrspools.ListAddressPoolsRequest{})
|
listStoragePolicies, err := client.SDN().AddressPools().List(context.Background(), adrspools.ListAddressPoolsRequest{})
|
||||||
if len(listStoragePolicies.Pools) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.AddressPools.List failed: %v", err)
|
||||||
|
} else if len(listStoragePolicies.Pools) > 0 {
|
||||||
id := listStoragePolicies.Pools[0].ID
|
id := listStoragePolicies.Pools[0].ID
|
||||||
bytes, err = client.SDN().AddressPools().GetRaw(context.Background(), adrspools.GetRequest{ID: id})
|
bytes, err = client.SDN().AddressPools().GetRaw(context.Background(), adrspools.GetRequest{ID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1131,8 +1233,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Security policies list", bytes, secpolicies.SecurityPolicyList{}, t)
|
getResult("Security policies list", bytes, secpolicies.SecurityPolicyList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listPolicies, _ := client.SDN().SecurityPolicies().List(context.Background(), secpolicies.ListRequest{})
|
listPolicies, err := client.SDN().SecurityPolicies().List(context.Background(), secpolicies.ListRequest{})
|
||||||
if len(listPolicies) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.SecurityPolicies.List failed: %v", err)
|
||||||
|
} else if len(listPolicies) > 0 {
|
||||||
id := listPolicies[0].ID
|
id := listPolicies[0].ID
|
||||||
bytes, err = client.SDN().SecurityPolicies().GetRaw(context.Background(), secpolicies.GetRequest{ID: id})
|
bytes, err = client.SDN().SecurityPolicies().GetRaw(context.Background(), secpolicies.GetRequest{ID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1150,8 +1254,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Security policy rule list", bytes, rule.SecurityRulesList{}, t)
|
getResult("Security policy rule list", bytes, rule.SecurityRulesList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listRules, _ := client.SDN().SecurityPolicies().Rule().List(context.Background(), rule.ListRequest{})
|
listRules, err := client.SDN().SecurityPolicies().Rule().List(context.Background(), rule.ListRequest{})
|
||||||
if len(listRules) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.SecurityPolicies.Rule.List failed: %v", err)
|
||||||
|
} else if len(listRules) > 0 {
|
||||||
id := listRules[0].ID
|
id := listRules[0].ID
|
||||||
securityPolicyID := listRules[0].SecurityPolicyID
|
securityPolicyID := listRules[0].SecurityPolicyID
|
||||||
bytes, err = client.SDN().SecurityPolicies().Rule().GetRaw(context.Background(), rule.GetRequest{
|
bytes, err = client.SDN().SecurityPolicies().Rule().GetRaw(context.Background(), rule.GetRequest{
|
||||||
@@ -1173,8 +1279,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("ExtNet list", bytes, extnet_sdn.ListExtNet{}, t)
|
getResult("ExtNet list", bytes, extnet_sdn.ListExtNet{}, t)
|
||||||
// Get
|
// Get
|
||||||
listExtNet, _ := client.SDN().ExtNet().List(context.Background(), extnet_sdn.ListRequest{})
|
listExtNet, err := client.SDN().ExtNet().List(context.Background(), extnet_sdn.ListRequest{})
|
||||||
if len(listExtNet) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.ExtNet.List failed: %v", err)
|
||||||
|
} else if len(listExtNet) > 0 {
|
||||||
id := listExtNet[0].ID
|
id := listExtNet[0].ID
|
||||||
bytes, err = client.SDN().ExtNet().GetRaw(context.Background(), extnet_sdn.GetRequest{ExtNetID: id})
|
bytes, err = client.SDN().ExtNet().GetRaw(context.Background(), extnet_sdn.GetRequest{ExtNetID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1193,8 +1301,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("NetObjGroup list", bytes, netobjgroups.NetObjGroupList{}, t)
|
getResult("NetObjGroup list", bytes, netobjgroups.NetObjGroupList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listNetObjGroups, _ := client.SDN().NetworkObjectGroups().List(context.Background(), netobjgroups.ListRequest{})
|
listNetObjGroups, err := client.SDN().NetworkObjectGroups().List(context.Background(), netobjgroups.ListRequest{})
|
||||||
if len(listNetObjGroups.Objects) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.NetworkObjectGroups.List failed: %v", err)
|
||||||
|
} else if len(listNetObjGroups.Objects) > 0 {
|
||||||
id := listNetObjGroups.Objects[0].ID
|
id := listNetObjGroups.Objects[0].ID
|
||||||
bytes, err = client.SDN().NetworkObjectGroups().GetRaw(context.Background(), netobjgroups.GetRequest{NetObjGroupID: id})
|
bytes, err = client.SDN().NetworkObjectGroups().GetRaw(context.Background(), netobjgroups.GetRequest{NetObjGroupID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1213,8 +1323,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Segments list", bytes, segments.ListSegment{}, t)
|
getResult("Segments list", bytes, segments.ListSegment{}, t)
|
||||||
// Get
|
// Get
|
||||||
listSegments, _ := client.SDN().Segments().List(context.Background(), segments.ListRequest{})
|
listSegments, err := client.SDN().Segments().List(context.Background(), segments.ListRequest{})
|
||||||
if len(listSegments) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.Segments.List failed: %v", err)
|
||||||
|
} else if len(listSegments) > 0 {
|
||||||
id := listSegments[0].ID
|
id := listSegments[0].ID
|
||||||
bytes, err = client.SDN().Segments().GetRaw(context.Background(), segments.GetRequest{SegmentID: id})
|
bytes, err = client.SDN().Segments().GetRaw(context.Background(), segments.GetRequest{SegmentID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1233,8 +1345,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Hypervisors list", bytes, hypervisors.HypervisorsList{}, t)
|
getResult("Hypervisors list", bytes, hypervisors.HypervisorsList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listHypervisors, _ := client.SDN().Hypervisors().List(context.Background(), hypervisors.ListRequest{})
|
listHypervisors, err := client.SDN().Hypervisors().List(context.Background(), hypervisors.ListRequest{})
|
||||||
if len(listHypervisors) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.Hypervisors.List failed: %v", err)
|
||||||
|
} else if len(listHypervisors) > 0 {
|
||||||
id := listHypervisors[0].Name
|
id := listHypervisors[0].Name
|
||||||
bytes, err = client.SDN().Hypervisors().GetRaw(context.Background(), hypervisors.GetRequest{Name: id})
|
bytes, err = client.SDN().Hypervisors().GetRaw(context.Background(), hypervisors.GetRequest{Name: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1253,8 +1367,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("FloatingIPs list", bytes, flips.FloatingIPsList{}, t)
|
getResult("FloatingIPs list", bytes, flips.FloatingIPsList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listFloatingIPs, _ := client.SDN().FloatingIPs().List(context.Background(), flips.ListRequest{})
|
listFloatingIPs, err := client.SDN().FloatingIPs().List(context.Background(), flips.ListRequest{})
|
||||||
if len(listFloatingIPs.Objects) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.FloatingIPs.List failed: %v", err)
|
||||||
|
} else if len(listFloatingIPs.Objects) > 0 {
|
||||||
id := listFloatingIPs.Objects[0].ID
|
id := listFloatingIPs.Objects[0].ID
|
||||||
bytes, err = client.SDN().FloatingIPs().GetRaw(context.Background(), flips.GetRequest{FloatingIPID: id})
|
bytes, err = client.SDN().FloatingIPs().GetRaw(context.Background(), flips.GetRequest{FloatingIPID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1273,8 +1389,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Logical ports list", bytes, logicalports.LogicalPortsList{}, t)
|
getResult("Logical ports list", bytes, logicalports.LogicalPortsList{}, t)
|
||||||
// Get
|
// Get
|
||||||
listLP, _ := client.SDN().LogicalPorts().List(context.Background(), logicalports.ListRequest{})
|
listLP, err := client.SDN().LogicalPorts().List(context.Background(), logicalports.ListRequest{})
|
||||||
if len(listLP.Ports) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.LogicalPorts.List failed: %v", err)
|
||||||
|
} else if len(listLP.Ports) > 0 {
|
||||||
id := listStoragePolicies.Pools[0].ID
|
id := listStoragePolicies.Pools[0].ID
|
||||||
bytes, err = client.SDN().LogicalPorts().GetRaw(context.Background(), logicalports.GetRequest{ID: id})
|
bytes, err = client.SDN().LogicalPorts().GetRaw(context.Background(), logicalports.GetRequest{ID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1293,8 +1411,10 @@ func TestGetListSDNAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
getResult("Routers list", bytes, routers.RoutersList{}, t)
|
getResult("Routers list", bytes, routers.RoutersList{}, t)
|
||||||
// Get
|
// Get
|
||||||
routerList, _ := client.SDN().Routers().List(context.Background(), routers.ListRequest{})
|
routerList, err := client.SDN().Routers().List(context.Background(), routers.ListRequest{})
|
||||||
if len(routerList) > 0 {
|
if err != nil {
|
||||||
|
t.Errorf("Can not test get because SDN.Routers.List failed: %v", err)
|
||||||
|
} else if len(routerList) > 0 {
|
||||||
id := routerList[0].ID
|
id := routerList[0].ID
|
||||||
bytes, err = client.SDN().Routers().GetRaw(context.Background(), routers.GetRequest{ID: id})
|
bytes, err = client.SDN().Routers().GetRaw(context.Background(), routers.GetRequest{ID: id})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -694,6 +694,12 @@ func getRequestsMapCloudbroker() map[string]interface{} {
|
|||||||
"/restmachine/cloudbroker/compute/migrate_abort": compute_cb.MigrateAbortRequest{},
|
"/restmachine/cloudbroker/compute/migrate_abort": compute_cb.MigrateAbortRequest{},
|
||||||
"/restmachine/cloudbroker/compute/start_migration_out": compute_cb.StartMigrationOutRequest{},
|
"/restmachine/cloudbroker/compute/start_migration_out": compute_cb.StartMigrationOutRequest{},
|
||||||
"/restmachine/cloudbroker/compute/stop_migration_out": compute_cb.StopMigrationOutRequest{},
|
"/restmachine/cloudbroker/compute/stop_migration_out": compute_cb.StopMigrationOutRequest{},
|
||||||
|
"/restmachine/cloudbroker/compute/migrate_v2_resolve": compute_cb.MigrateV2ResolveRequest{},
|
||||||
|
"/restmachine/cloudbroker/compute/migrate_v2_list": compute_cb.MigrateV2ListRequest{},
|
||||||
|
"/restmachine/cloudbroker/compute/migrate_v2_get": compute_cb.MigrateV2GetRequest{},
|
||||||
|
"/restmachine/cloudbroker/compute/migrate_v2_abort": compute_cb.MigrateV2AbortRequest{},
|
||||||
|
"/restmachine/cloudbroker/compute/migrate_v2_cleanup": compute_cb.MigrateV2CleanupRequest{},
|
||||||
|
"/restmachine/cloudbroker/compute/migrate_v2": compute_cb.MigrateV2Request{},
|
||||||
|
|
||||||
// disks
|
// disks
|
||||||
"/restmachine/cloudbroker/disks/change_disk_storage_policy": disks_cb.ChangeDiskStoragePolicyRequest{},
|
"/restmachine/cloudbroker/disks/change_disk_storage_policy": disks_cb.ChangeDiskStoragePolicyRequest{},
|
||||||
@@ -1173,16 +1179,6 @@ func getRequestsMapCloudbroker() map[string]interface{} {
|
|||||||
"/restmachine/cloudbroker/zone/test_cpu_alignment_profile": zone_cb.TestCPUAlignmentProfileRequest{},
|
"/restmachine/cloudbroker/zone/test_cpu_alignment_profile": zone_cb.TestCPUAlignmentProfileRequest{},
|
||||||
"/restmachine/cloudbroker/zone/set_resources_limit": zone_cb.SetResourcesLimitRequest{},
|
"/restmachine/cloudbroker/zone/set_resources_limit": zone_cb.SetResourcesLimitRequest{},
|
||||||
"/restmachine/cloudbroker/zone/update_cpu_alignment_profile": zone_cb.UpdateCPUAlignmentProfileRequest{},
|
"/restmachine/cloudbroker/zone/update_cpu_alignment_profile": zone_cb.UpdateCPUAlignmentProfileRequest{},
|
||||||
|
|
||||||
// security policy
|
|
||||||
"/sdn/security_policy/create": secpolicies.CreateRequest{},
|
|
||||||
"/sdn/security_policy/delete": secpolicies.DeleteRequest{},
|
|
||||||
"/sdn/security_policy/get": secpolicies.GetRequest{},
|
|
||||||
"/sdn/security_policy/list": secpolicies.ListRequest{},
|
|
||||||
"/sdn/security_policy/move": secpolicies.MoveRequest{},
|
|
||||||
"/sdn/security_policy/update": secpolicies.UpdateRequest{},
|
|
||||||
"/sdn/security_policy/rule/get": rule.GetRequest{},
|
|
||||||
"/sdn/security_policy/rule/list": rule.ListRequest{},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1211,6 +1207,16 @@ func getRequestsMapSDN() map[string]interface{} {
|
|||||||
"/restmachine/sdn/default_security_policy/list": defsecpolicies.ListRequest{},
|
"/restmachine/sdn/default_security_policy/list": defsecpolicies.ListRequest{},
|
||||||
"/restmachine/sdn/default_security_policy/update": defsecpolicies.UpdateRequest{},
|
"/restmachine/sdn/default_security_policy/update": defsecpolicies.UpdateRequest{},
|
||||||
|
|
||||||
|
// security policy
|
||||||
|
"/restmachine/sdn/security_policy/create": secpolicies.CreateRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/delete": secpolicies.DeleteRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/get": secpolicies.GetRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/list": secpolicies.ListRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/move": secpolicies.MoveRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/update": secpolicies.UpdateRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/rule/get": rule.GetRequest{},
|
||||||
|
"/restmachine/sdn/security_policy/rule/list": rule.ListRequest{},
|
||||||
|
|
||||||
// extnet
|
// extnet
|
||||||
"/restmachine/sdn/external_network/port_add": extnet_sdn.PortAddRequest{},
|
"/restmachine/sdn/external_network/port_add": extnet_sdn.PortAddRequest{},
|
||||||
"/restmachine/sdn/external_network/port_update": extnet_sdn.PortUpdateRequest{},
|
"/restmachine/sdn/external_network/port_update": extnet_sdn.PortUpdateRequest{},
|
||||||
|
|||||||
446
tests/platform_upgrade/sdk_calls.go
Normal file
446
tests/platform_upgrade/sdk_calls.go
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// transport defines which struct tags are used to serialize request on the wire
|
||||||
|
const (
|
||||||
|
transportForm = "form"
|
||||||
|
transportJSON = "json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sentField describes one request parameter exactly as SDK puts it on the wire
|
||||||
|
type sentField struct {
|
||||||
|
// Name of the parameter on the wire
|
||||||
|
Name string
|
||||||
|
// Name of the go field (for messages)
|
||||||
|
GoName string
|
||||||
|
// Go type of the field, nil if it can not be resolved
|
||||||
|
Type reflect.Type
|
||||||
|
// Field is not sent when it has zero value
|
||||||
|
OmitEmpty bool
|
||||||
|
// Value of `validate` tag
|
||||||
|
Validate string
|
||||||
|
}
|
||||||
|
|
||||||
|
// sdkCall describes one DecortApiCall* invocation found in SDK sources
|
||||||
|
type sdkCall struct {
|
||||||
|
// Directory of package the call was found in
|
||||||
|
Dir string
|
||||||
|
// Name of the type passed as params (may be unexported wrapper), empty for nil params
|
||||||
|
TypeName string
|
||||||
|
Transport string
|
||||||
|
// Name of function the call was found in
|
||||||
|
FuncName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// sdkIndex stores parsed SDK packages: struct declarations and API calls by url
|
||||||
|
type sdkIndex struct {
|
||||||
|
// dir -> type name -> type expression
|
||||||
|
types map[string]map[string]ast.Expr
|
||||||
|
// url (e.g. "/cloudapi/compute/start") -> calls
|
||||||
|
calls map[string][]sdkCall
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
sdkIndexOnce sync.Once
|
||||||
|
sdkIndexCached *sdkIndex
|
||||||
|
sdkIndexErr error
|
||||||
|
)
|
||||||
|
|
||||||
|
// getSDKIndex parses SDK sources in ../../pkg once per test run
|
||||||
|
func getSDKIndex() (*sdkIndex, error) {
|
||||||
|
sdkIndexOnce.Do(func() {
|
||||||
|
sdkIndexCached, sdkIndexErr = buildSDKIndex("../../pkg")
|
||||||
|
})
|
||||||
|
return sdkIndexCached, sdkIndexErr
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSDKIndex(root string) (*sdkIndex, error) {
|
||||||
|
idx := newSDKIndex()
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
err := filepath.WalkDir(root, func(path string, d os.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if d.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
file, err := parser.ParseFile(fset, path, nil, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
idx.addFile(filepath.Dir(path), file)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return idx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSDKIndex() *sdkIndex {
|
||||||
|
return &sdkIndex{
|
||||||
|
types: make(map[string]map[string]ast.Expr),
|
||||||
|
calls: make(map[string][]sdkCall),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addFile collects type declarations and API calls of one file
|
||||||
|
func (idx *sdkIndex) addFile(dir string, file *ast.File) {
|
||||||
|
if idx.types[dir] == nil {
|
||||||
|
idx.types[dir] = make(map[string]ast.Expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, decl := range file.Decls {
|
||||||
|
switch d := decl.(type) {
|
||||||
|
case *ast.GenDecl:
|
||||||
|
for _, spec := range d.Specs {
|
||||||
|
if ts, ok := spec.(*ast.TypeSpec); ok {
|
||||||
|
idx.types[dir][ts.Name.Name] = ts.Type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *ast.FuncDecl:
|
||||||
|
if d.Body != nil {
|
||||||
|
idx.addFuncCalls(dir, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// addFuncCalls finds DecortApiCall* invocations in function body and resolves url and type of params
|
||||||
|
func (idx *sdkIndex) addFuncCalls(dir string, fn *ast.FuncDecl) {
|
||||||
|
// variable name -> type name
|
||||||
|
varTypes := make(map[string]string)
|
||||||
|
for _, field := range fn.Type.Params.List {
|
||||||
|
for _, name := range field.Names {
|
||||||
|
varTypes[name.Name] = typeNameOf(field.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// variable name -> last assigned string literal
|
||||||
|
strVars := make(map[string]string)
|
||||||
|
|
||||||
|
ast.Inspect(fn.Body, func(n ast.Node) bool {
|
||||||
|
switch node := n.(type) {
|
||||||
|
case *ast.AssignStmt:
|
||||||
|
for i, lhs := range node.Lhs {
|
||||||
|
ident, ok := lhs.(*ast.Ident)
|
||||||
|
if !ok || i >= len(node.Rhs) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if s, ok := stringLiteral(node.Rhs[i]); ok {
|
||||||
|
strVars[ident.Name] = s
|
||||||
|
}
|
||||||
|
if name := typeNameOfValue(node.Rhs[i]); name != "" {
|
||||||
|
varTypes[ident.Name] = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *ast.ValueSpec:
|
||||||
|
for i, name := range node.Names {
|
||||||
|
if node.Type != nil {
|
||||||
|
varTypes[name.Name] = typeNameOf(node.Type)
|
||||||
|
}
|
||||||
|
if i < len(node.Values) {
|
||||||
|
if s, ok := stringLiteral(node.Values[i]); ok {
|
||||||
|
strVars[name.Name] = s
|
||||||
|
}
|
||||||
|
if tn := typeNameOfValue(node.Values[i]); tn != "" {
|
||||||
|
varTypes[name.Name] = tn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *ast.CallExpr:
|
||||||
|
sel, ok := node.Fun.(*ast.SelectorExpr)
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var urlArg, paramsArg ast.Expr
|
||||||
|
transport := transportForm
|
||||||
|
switch sel.Sel.Name {
|
||||||
|
case "DecortApiCall", "DecortApiCallMP":
|
||||||
|
if len(node.Args) != 4 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
urlArg, paramsArg = node.Args[2], node.Args[3]
|
||||||
|
case "DecortApiCallCtype":
|
||||||
|
if len(node.Args) != 5 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
urlArg, paramsArg = node.Args[2], node.Args[4]
|
||||||
|
if ctype, ok := node.Args[3].(*ast.SelectorExpr); ok && ctype.Sel.Name == "MIMEJSON" {
|
||||||
|
transport = transportJSON
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
url, ok := stringLiteral(urlArg)
|
||||||
|
if !ok {
|
||||||
|
ident, isIdent := urlArg.(*ast.Ident)
|
||||||
|
if !isIdent {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if url, ok = strVars[ident.Name]; !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call := sdkCall{Dir: dir, Transport: transport, FuncName: fn.Name.Name}
|
||||||
|
switch p := paramsArg.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
if p.Name != "nil" {
|
||||||
|
call.TypeName = varTypes[p.Name]
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
call.TypeName = typeNameOfValue(paramsArg)
|
||||||
|
}
|
||||||
|
idx.calls[url] = append(idx.calls[url], call)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringLiteral(e ast.Expr) (string, bool) {
|
||||||
|
lit, ok := e.(*ast.BasicLit)
|
||||||
|
if !ok || lit.Kind != token.STRING {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
s, err := strconv.Unquote(lit.Value)
|
||||||
|
return s, err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeNameOfValue returns type name of expressions like T{...} or &T{...}
|
||||||
|
func typeNameOfValue(e ast.Expr) string {
|
||||||
|
switch v := e.(type) {
|
||||||
|
case *ast.CompositeLit:
|
||||||
|
return typeNameOf(v.Type)
|
||||||
|
case *ast.UnaryExpr:
|
||||||
|
return typeNameOfValue(v.X)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// typeNameOf returns name of local named type (T or *T), empty string otherwise
|
||||||
|
func typeNameOf(e ast.Expr) string {
|
||||||
|
switch v := e.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
return v.Name
|
||||||
|
case *ast.StarExpr:
|
||||||
|
return typeNameOf(v.X)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// callsForPath returns SDK calls for platform path like "/restmachine/cloudapi/compute/start"
|
||||||
|
func (idx *sdkIndex) callsForPath(path string) []sdkCall {
|
||||||
|
return idx.calls[strings.TrimPrefix(path, "/restmachine")]
|
||||||
|
}
|
||||||
|
|
||||||
|
// sentFields returns flattened list of parameters SDK puts on the wire for the call
|
||||||
|
func (idx *sdkIndex) sentFields(call sdkCall) ([]sentField, bool) {
|
||||||
|
if call.TypeName == "" {
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
expr, ok := idx.types[call.Dir][call.TypeName]
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
st, ok := expr.(*ast.StructType)
|
||||||
|
if !ok {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
fields := idx.structFields(call.Dir, st, call.Transport, map[string]bool{call.TypeName: true})
|
||||||
|
|
||||||
|
// serialized wrapper field inherits `validate` of the skipped (url:"-") request field with the same json name
|
||||||
|
if call.Transport == transportForm {
|
||||||
|
skipped := idx.skippedFormFields(call.Dir, st, map[string]bool{call.TypeName: true})
|
||||||
|
for i := range fields {
|
||||||
|
if fields[i].Validate != "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if validate, ok := skipped[strings.TrimSpace(fields[i].Name)]; ok {
|
||||||
|
fields[i].Validate = validate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// skippedFormFields returns json name -> validate tag of fields that are not sent in form requests (url:"-")
|
||||||
|
func (idx *sdkIndex) skippedFormFields(dir string, st *ast.StructType, visited map[string]bool) map[string]string {
|
||||||
|
result := make(map[string]string)
|
||||||
|
for _, field := range st.Fields.List {
|
||||||
|
var tag reflect.StructTag
|
||||||
|
if field.Tag != nil {
|
||||||
|
if s, err := strconv.Unquote(field.Tag.Value); err == nil {
|
||||||
|
tag = reflect.StructTag(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
urlTag, hasURLTag := tag.Lookup("url")
|
||||||
|
|
||||||
|
if len(field.Names) == 0 && !hasURLTag {
|
||||||
|
name := typeNameOf(field.Type)
|
||||||
|
if embedded, ok := idx.types[dir][name].(*ast.StructType); ok && !visited[name] {
|
||||||
|
visited[name] = true
|
||||||
|
for k, v := range idx.skippedFormFields(dir, embedded, visited) {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
delete(visited, name)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if urlTag != "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
jsonName := strings.TrimSpace(strings.Split(tag.Get("json"), ",")[0])
|
||||||
|
if jsonName != "" && jsonName != "-" {
|
||||||
|
result[jsonName] = tag.Get("validate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (idx *sdkIndex) structFields(dir string, st *ast.StructType, transport string, visited map[string]bool) []sentField {
|
||||||
|
var result []sentField
|
||||||
|
for _, field := range st.Fields.List {
|
||||||
|
var tag reflect.StructTag
|
||||||
|
if field.Tag != nil {
|
||||||
|
if s, err := strconv.Unquote(field.Tag.Value); err == nil {
|
||||||
|
tag = reflect.StructTag(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wireTag, hasWireTag := tag.Lookup(transportTagKey(transport))
|
||||||
|
|
||||||
|
// embedded struct without tag is flattened by both encoding/json and go-querystring
|
||||||
|
if len(field.Names) == 0 && !hasWireTag {
|
||||||
|
name := typeNameOf(field.Type)
|
||||||
|
if embedded, ok := idx.types[dir][name].(*ast.StructType); ok && !visited[name] {
|
||||||
|
visited[name] = true
|
||||||
|
result = append(result, idx.structFields(dir, embedded, transport, visited)...)
|
||||||
|
delete(visited, name)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
goNames := make([]string, 0, len(field.Names))
|
||||||
|
for _, n := range field.Names {
|
||||||
|
goNames = append(goNames, n.Name)
|
||||||
|
}
|
||||||
|
if len(goNames) == 0 {
|
||||||
|
goNames = append(goNames, typeNameOf(field.Type))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, goName := range goNames {
|
||||||
|
if !ast.IsExported(goName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, omitEmpty, skip := parseWireTag(wireTag, goName)
|
||||||
|
if skip {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result = append(result, sentField{
|
||||||
|
Name: name,
|
||||||
|
GoName: goName,
|
||||||
|
Type: idx.resolveType(dir, field.Type, map[string]bool{}),
|
||||||
|
OmitEmpty: omitEmpty,
|
||||||
|
Validate: tag.Get("validate"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func transportTagKey(transport string) string {
|
||||||
|
if transport == transportJSON {
|
||||||
|
return "json"
|
||||||
|
}
|
||||||
|
return "url"
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseWireTag returns wire name of the field, omitempty flag and whether the field is skipped (tag "-")
|
||||||
|
func parseWireTag(tag, goName string) (string, bool, bool) {
|
||||||
|
parts := strings.Split(tag, ",")
|
||||||
|
// keep tag name as is (including spaces) so that typos in tags are reported
|
||||||
|
name := parts[0]
|
||||||
|
if name == "-" && len(parts) == 1 {
|
||||||
|
return "", false, true
|
||||||
|
}
|
||||||
|
if name == "" {
|
||||||
|
name = goName
|
||||||
|
}
|
||||||
|
var omitEmpty bool
|
||||||
|
for _, opt := range parts[1:] {
|
||||||
|
if strings.TrimSpace(opt) == "omitempty" {
|
||||||
|
omitEmpty = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name, omitEmpty, false
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
emptyInterfaceType = reflect.TypeOf((*interface{})(nil)).Elem()
|
||||||
|
structPlaceholder = reflect.TypeOf(struct{}{})
|
||||||
|
basicTypes = map[string]reflect.Type{
|
||||||
|
"bool": reflect.TypeOf(false),
|
||||||
|
"string": reflect.TypeOf(""),
|
||||||
|
"int": reflect.TypeOf(int(0)),
|
||||||
|
"int8": reflect.TypeOf(int8(0)),
|
||||||
|
"int16": reflect.TypeOf(int16(0)),
|
||||||
|
"int32": reflect.TypeOf(int32(0)),
|
||||||
|
"int64": reflect.TypeOf(int64(0)),
|
||||||
|
"uint": reflect.TypeOf(uint(0)),
|
||||||
|
"uint8": reflect.TypeOf(uint8(0)),
|
||||||
|
"uint16": reflect.TypeOf(uint16(0)),
|
||||||
|
"uint32": reflect.TypeOf(uint32(0)),
|
||||||
|
"uint64": reflect.TypeOf(uint64(0)),
|
||||||
|
"float32": reflect.TypeOf(float32(0)),
|
||||||
|
"float64": reflect.TypeOf(float64(0)),
|
||||||
|
"any": emptyInterfaceType,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// resolveType converts type expression to reflect.Type for kind comparison (nil for types from other packages)
|
||||||
|
func (idx *sdkIndex) resolveType(dir string, e ast.Expr, visited map[string]bool) reflect.Type {
|
||||||
|
switch v := e.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
if t, ok := basicTypes[v.Name]; ok {
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
if visited[v.Name] {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
underlying, ok := idx.types[dir][v.Name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
visited[v.Name] = true
|
||||||
|
return idx.resolveType(dir, underlying, visited)
|
||||||
|
case *ast.StarExpr:
|
||||||
|
return idx.resolveType(dir, v.X, visited)
|
||||||
|
case *ast.StructType:
|
||||||
|
return structPlaceholder
|
||||||
|
case *ast.InterfaceType:
|
||||||
|
return emptyInterfaceType
|
||||||
|
case *ast.ArrayType:
|
||||||
|
elem := idx.resolveType(dir, v.Elt, visited)
|
||||||
|
if elem == nil {
|
||||||
|
elem = emptyInterfaceType
|
||||||
|
}
|
||||||
|
return reflect.SliceOf(elem)
|
||||||
|
case *ast.MapType:
|
||||||
|
return reflect.MapOf(reflect.TypeOf(""), emptyInterfaceType)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -5,27 +5,72 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// extractTypeFromSchema extracts type from schema, handling oneOf cases
|
// platformParam describes one request parameter from platform swagger
|
||||||
// When oneOf contains a type and null, it returns the non-null type
|
type platformParam struct {
|
||||||
|
Name string
|
||||||
|
// OpenAPI type: integer, string, boolean, number, array, object or empty if unknown
|
||||||
|
Type string
|
||||||
|
// OpenAPI type of array items, empty if unknown
|
||||||
|
Items string
|
||||||
|
Required bool
|
||||||
|
// Value of "default" from swagger, nil if not set
|
||||||
|
Default interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractTypeFromSchema extracts non-null type from "type" (string or array), "oneOf"/"anyOf" or "$ref" (object)
|
||||||
func extractTypeFromSchema(schema map[string]interface{}) string {
|
func extractTypeFromSchema(schema map[string]interface{}) string {
|
||||||
// Check for direct type
|
switch typ := schema["type"].(type) {
|
||||||
if paramType, ok := schema["type"].(string); ok {
|
case string:
|
||||||
return paramType
|
return typ
|
||||||
|
case []interface{}:
|
||||||
|
for _, item := range typ {
|
||||||
|
if s, ok := item.(string); ok && s != "null" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for oneOf
|
for _, key := range []string{"oneOf", "anyOf"} {
|
||||||
if oneOf, ok := schema["oneOf"].([]interface{}); ok {
|
variants, ok := schema[key].([]interface{})
|
||||||
for _, item := range oneOf {
|
if !ok {
|
||||||
if itemMap, ok := item.(map[string]interface{}); ok {
|
continue
|
||||||
if itemType, ok := itemMap["type"].(string); ok {
|
}
|
||||||
// Skip null type, return the first non-null type found
|
for _, variant := range variants {
|
||||||
if itemType != "null" {
|
if variantMap, ok := variant.(map[string]interface{}); ok {
|
||||||
return itemType
|
if variantType := extractTypeFromSchema(variantMap); variantType != "" && variantType != "null" {
|
||||||
}
|
return variantType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := schema["$ref"]; ok {
|
||||||
|
return "object"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractItemsType extracts type of array items from schema, including arrays declared inside oneOf/anyOf
|
||||||
|
func extractItemsType(schema map[string]interface{}) string {
|
||||||
|
if items, ok := schema["items"].(map[string]interface{}); ok {
|
||||||
|
return extractTypeFromSchema(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, key := range []string{"oneOf", "anyOf"} {
|
||||||
|
variants, ok := schema[key].([]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, variant := range variants {
|
||||||
|
if variantMap, ok := variant.(map[string]interface{}); ok && extractTypeFromSchema(variantMap) == "array" {
|
||||||
|
if items := extractItemsType(variantMap); items != "" {
|
||||||
|
return items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,150 +79,84 @@ func extractTypeFromSchema(schema map[string]interface{}) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func getParameters(input map[string]interface{}) []interface{} {
|
// getParameters returns request parameters of all methods, content types and query/path parameters of a path
|
||||||
var emptySlice []interface{}
|
func getParameters(input map[string]interface{}) []platformParam {
|
||||||
methods := []string{"get", "post", "put", "delete", "patch", "head", "options"}
|
params := make(map[string]platformParam)
|
||||||
|
add := func(name string, schema map[string]interface{}, required bool) {
|
||||||
var methodData interface{}
|
p := platformParam{Name: name, Required: required}
|
||||||
found := false
|
if schema != nil {
|
||||||
|
p.Type = extractTypeFromSchema(schema)
|
||||||
for _, method := range methods {
|
if p.Type == "array" {
|
||||||
if data, ok := input[method]; ok {
|
p.Items = extractItemsType(schema)
|
||||||
methodData = data
|
}
|
||||||
found = true
|
p.Default = schema["default"]
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
if prev, ok := params[name]; ok {
|
||||||
|
p.Required = p.Required || prev.Required
|
||||||
|
if p.Type == "" {
|
||||||
|
p.Type, p.Items = prev.Type, prev.Items
|
||||||
|
}
|
||||||
|
if p.Default == nil {
|
||||||
|
p.Default = prev.Default
|
||||||
|
}
|
||||||
|
}
|
||||||
|
params[name] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found {
|
for _, method := range []string{"get", "post", "put", "delete", "patch", "head", "options"} {
|
||||||
return emptySlice
|
operation, ok := input[method].(map[string]interface{})
|
||||||
}
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
parameters, ok := methodData.(map[string]interface{})
|
if requestBody, ok := operation["requestBody"].(map[string]interface{}); ok {
|
||||||
if !ok {
|
content, _ := requestBody["content"].(map[string]interface{})
|
||||||
return emptySlice
|
for _, media := range content {
|
||||||
}
|
mediaMap, _ := media.(map[string]interface{})
|
||||||
|
schema, _ := mediaMap["schema"].(map[string]interface{})
|
||||||
var result []interface{}
|
if schema == nil {
|
||||||
|
continue
|
||||||
if requestBody, ok := parameters["requestBody"].(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
|
|
||||||
var schemaData map[string]interface{}
|
|
||||||
var found bool
|
|
||||||
|
|
||||||
if formData, ok := content["application/x-www-form-urlencoded"].(map[string]interface{}); ok {
|
|
||||||
if schema, ok := formData["schema"].(map[string]interface{}); ok {
|
|
||||||
schemaData = schema
|
|
||||||
found = true
|
|
||||||
}
|
}
|
||||||
} else if jsonData, ok := content["application/json"].(map[string]interface{}); ok {
|
requiredFields := make(map[string]bool)
|
||||||
if schema, ok := jsonData["schema"].(map[string]interface{}); ok {
|
if req, ok := schema["required"].([]interface{}); ok {
|
||||||
schemaData = schema
|
for _, r := range req {
|
||||||
found = true
|
if reqStr, ok := r.(string); ok {
|
||||||
|
requiredFields[reqStr] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if multipartData, ok := content["multipart/form-data"].(map[string]interface{}); ok {
|
properties, _ := schema["properties"].(map[string]interface{})
|
||||||
if schema, ok := multipartData["schema"].(map[string]interface{}); ok {
|
for name, prop := range properties {
|
||||||
schemaData = schema
|
propMap, _ := prop.(map[string]interface{})
|
||||||
found = true
|
add(name, propMap, requiredFields[name])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if found && schemaData != nil {
|
if parameters, ok := operation["parameters"].([]interface{}); ok {
|
||||||
if properties, ok := schemaData["properties"].(map[string]interface{}); ok {
|
for _, p := range parameters {
|
||||||
requiredFields := make(map[string]bool)
|
param, ok := p.(map[string]interface{})
|
||||||
if req, ok := schemaData["required"].([]interface{}); ok {
|
if !ok {
|
||||||
for _, r := range req {
|
continue
|
||||||
if reqStr, ok := r.(string); ok {
|
|
||||||
requiredFields[reqStr] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for name, prop := range properties {
|
|
||||||
propMap, ok := prop.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newParam := make(map[string]interface{})
|
|
||||||
newParam["name"] = name
|
|
||||||
propType := extractTypeFromSchema(propMap)
|
|
||||||
if propType != "" {
|
|
||||||
newParam["type"] = propType
|
|
||||||
}
|
|
||||||
newParam["required"] = requiredFields[name]
|
|
||||||
if propType == "array" {
|
|
||||||
// Try to get items from propMap first
|
|
||||||
if items, ok := propMap["items"].(map[string]interface{}); ok {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
name, ok := param["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
schema, _ := param["schema"].(map[string]interface{})
|
||||||
|
required, _ := param["required"].(bool)
|
||||||
|
add(name, schema, required)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if params, ok := parameters["parameters"].([]interface{}); ok {
|
result := make([]platformParam, 0, len(params))
|
||||||
for _, p := range params {
|
for _, p := range params {
|
||||||
param, ok := p.(map[string]interface{})
|
result = append(result, p)
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
newParam := make(map[string]interface{})
|
|
||||||
if name, ok := param["name"].(string); ok {
|
|
||||||
newParam["name"] = name
|
|
||||||
}
|
|
||||||
if schema, ok := param["schema"].(map[string]interface{}); ok {
|
|
||||||
paramType := extractTypeFromSchema(schema)
|
|
||||||
if paramType != "" {
|
|
||||||
newParam["type"] = paramType
|
|
||||||
}
|
|
||||||
if paramType == "array" {
|
|
||||||
if items, ok := schema["items"].(map[string]interface{}); ok {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Handle required field
|
|
||||||
if required, ok := param["required"].(bool); ok {
|
|
||||||
newParam["required"] = required
|
|
||||||
} else {
|
|
||||||
newParam["required"] = false
|
|
||||||
}
|
|
||||||
result = append(result, newParam)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
sort.Slice(result, func(i, j int) bool { return result[i].Name < result[j].Name })
|
||||||
|
|
||||||
if len(result) > 0 {
|
return result
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
return emptySlice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBytesFromJSON(fileName string, t *testing.T) []byte {
|
func getBytesFromJSON(fileName string, t *testing.T) []byte {
|
||||||
@@ -195,6 +174,7 @@ func getBytesFromJSON(fileName string, t *testing.T) []byte {
|
|||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getErrorsFromJSON compares platform requests from swagger with the values SDK passes to DecortApiCall*
|
||||||
func getErrorsFromJSON(bytes []byte, t *testing.T, cloud string) {
|
func getErrorsFromJSON(bytes []byte, t *testing.T, cloud string) {
|
||||||
var requests map[string]interface{}
|
var requests map[string]interface{}
|
||||||
|
|
||||||
@@ -209,227 +189,272 @@ func getErrorsFromJSON(bytes []byte, t *testing.T, cloud string) {
|
|||||||
t.Fatalf("Wrong cloud provided, expected `cloudapi`, `cloudbroker` or `sdn`, got %s", cloud)
|
t.Fatalf("Wrong cloud provided, expected `cloudapi`, `cloudbroker` or `sdn`, got %s", cloud)
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataLogs []string
|
index, err := getSDKIndex()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can not parse SDK sources: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
paths, err := getMapFromFile(bytes)
|
paths, err := getMapFromFile(bytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
i := 0
|
|
||||||
for k, v := range paths {
|
requestPaths := make([]string, 0, len(requests))
|
||||||
|
for k := range requests {
|
||||||
|
requestPaths = append(requestPaths, k)
|
||||||
|
}
|
||||||
|
sort.Strings(requestPaths)
|
||||||
|
|
||||||
|
var absentOnPlatform, invalidKeys []string
|
||||||
|
for _, k := range requestPaths {
|
||||||
|
if !strings.HasPrefix(k, "/restmachine/"+cloud+"/") {
|
||||||
|
invalidKeys = append(invalidKeys, k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
// exclude deprecated urls from analysis
|
// exclude deprecated urls from analysis
|
||||||
if !validateUrlFromJson(k) {
|
if !validateUrlFromJson(k) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
v, ok := paths[k]
|
||||||
params := getParameters(v.(map[string]interface{}))
|
|
||||||
structure, ok := requests[k]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
|
absentOnPlatform = append(absentOnPlatform, k)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
i++
|
|
||||||
typStruct := reflect.TypeOf(structure)
|
|
||||||
|
|
||||||
var errs []string
|
|
||||||
// empty request case
|
|
||||||
if len(params) == 0 && structure == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(params) != typStruct.NumField() {
|
|
||||||
errs = append(errs, fmt.Sprintf("Platform (%d) and golang structure (%d) have different amount of fields.", len(params), typStruct.NumField()))
|
|
||||||
}
|
|
||||||
paramMap := make(map[string]bool)
|
|
||||||
paramRequiredMap := make(map[string]bool)
|
|
||||||
for _, p := range params {
|
|
||||||
param, ok := p.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name, ok := param["name"].(string)
|
|
||||||
if ok {
|
|
||||||
paramMap[name] = true
|
|
||||||
required, ok := param["required"].(bool)
|
|
||||||
if ok {
|
|
||||||
paramRequiredMap[name] = required
|
|
||||||
} else {
|
|
||||||
paramRequiredMap[name] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, p := range params {
|
|
||||||
param, ok := p.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name, ok := param["name"].(string)
|
|
||||||
if !ok {
|
|
||||||
name = ""
|
|
||||||
}
|
|
||||||
required, ok := param["required"].(bool)
|
|
||||||
if !ok {
|
|
||||||
required = false
|
|
||||||
}
|
|
||||||
typ, ok := p.(map[string]interface{})["type"].(string)
|
|
||||||
if !ok {
|
|
||||||
typ = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var items string
|
|
||||||
if p.(map[string]interface{})["items"] != nil {
|
|
||||||
itemsTemp := p.(map[string]interface{})["items"]
|
|
||||||
if itemsTemp != nil {
|
|
||||||
itemsType := itemsTemp.(map[string]interface{})["type"]
|
|
||||||
if itemsType != nil {
|
|
||||||
items, ok = itemsType.(string)
|
|
||||||
if !ok {
|
|
||||||
items = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var found bool
|
|
||||||
for i := 0; i < typStruct.NumField(); i++ {
|
|
||||||
jsonTag := typStruct.Field(i).Tag.Get("json")
|
|
||||||
validation, _ := typStruct.Field(i).Tag.Lookup("validate")
|
|
||||||
|
|
||||||
if checkName(name, jsonTag) {
|
|
||||||
if !checkRequired(required, validation, typ) {
|
|
||||||
errs = append(errs, fmt.Sprintf("Field %s has different required parameters on the platform and in golang structure", name))
|
|
||||||
}
|
|
||||||
if !checkKind(typ, items, typStruct.Field(i).Type) {
|
|
||||||
errs = append(errs, fmt.Sprintf("Field %s has different type parameters on the platform and in golang structure", name))
|
|
||||||
}
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
errs = append(errs, fmt.Sprintf("Platform has field %s that golang structure doesn't", name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if required fields in Go structure are missing from platform JSON
|
|
||||||
// or if they exist but are not required on platform
|
|
||||||
for i := 0; i < typStruct.NumField(); i++ {
|
|
||||||
jsonTag := typStruct.Field(i).Tag.Get("json")
|
|
||||||
validation, _ := typStruct.Field(i).Tag.Lookup("validate")
|
|
||||||
|
|
||||||
fieldName := strings.Split(jsonTag, ",")[0]
|
|
||||||
if fieldName == "" || fieldName == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.Contains(validation, "required") {
|
|
||||||
if !paramMap[fieldName] {
|
|
||||||
errs = append(errs, fmt.Sprintf("Golang structure has required field %s that platform doesn't", fieldName))
|
|
||||||
} else {
|
|
||||||
platformRequired := paramRequiredMap[fieldName]
|
|
||||||
if !platformRequired {
|
|
||||||
fieldType := typStruct.Field(i).Type
|
|
||||||
if fieldType.Kind() == reflect.Bool {
|
|
||||||
errs = append(errs, fmt.Sprintf("Golang structure has required field %s that platform doesn't", fieldName))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
errs := checkPath(k, getParameters(v.(map[string]interface{})), index)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
msg := fmt.Sprintf("Path %s has following errors: %v", k, errs)
|
t.Errorf("Path %s has following errors: %v", k, errs)
|
||||||
t.Error(msg)
|
|
||||||
dataLogs = append(dataLogs, msg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(requests) != i {
|
if len(invalidKeys) > 0 {
|
||||||
msg := fmt.Sprintf("Amount of structure checked (%d) is not the same as amount of platform requests available (%d), please check getRequests func in code.",
|
t.Errorf("Request map for %s has keys that don't start with /restmachine/%s/ and are never checked: %v", cloud, cloud, invalidKeys)
|
||||||
i, len(requests))
|
}
|
||||||
t.Error(msg)
|
if len(absentOnPlatform) > 0 {
|
||||||
dataLogs = append(dataLogs, msg)
|
t.Errorf("Request map has paths that platform doesn't (remove them from request map): %v", absentOnPlatform)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkName checks if name field from platform has the same value as json tag in golang structure (maybe including omitempty)
|
// requestVariant is one distinct request SDK sends to a path (e.g. sync and async methods send different wrappers)
|
||||||
func checkName(name, tag string) bool {
|
type requestVariant struct {
|
||||||
return strings.Contains(tag, name)
|
FuncName string
|
||||||
|
Transport string
|
||||||
|
Fields []sentField
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkRequired checks if required field from platform has the same value as validate tag in golang structure
|
// checkPath compares platform parameters of a path with every distinct request SDK sends to this path
|
||||||
func checkRequired(required bool, validation, fieldType string) bool {
|
func checkPath(path string, params []platformParam, index *sdkIndex) []string {
|
||||||
if required && strings.Contains(validation, "required") {
|
calls := index.callsForPath(path)
|
||||||
return true
|
if len(calls) == 0 {
|
||||||
}
|
return []string{"SDK call for this path is not found in sources, can not check it"}
|
||||||
if required && (!strings.Contains(validation, "omitempty") && validation != "") {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if !required && (validation == "" || strings.Contains(validation, "omitempty")) {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if fieldType == "boolean" {
|
type variantKey struct{ dir, typeName, transport string }
|
||||||
return true // otherwise we have issues with setting false/true
|
seen := make(map[variantKey]bool)
|
||||||
|
var variants []requestVariant
|
||||||
|
var errs []string
|
||||||
|
|
||||||
|
for _, call := range calls {
|
||||||
|
key := variantKey{call.Dir, call.TypeName, call.Transport}
|
||||||
|
if seen[key] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[key] = true
|
||||||
|
|
||||||
|
fields, ok := index.sentFields(call)
|
||||||
|
if !ok {
|
||||||
|
errs = append(errs, fmt.Sprintf("can not resolve type %s sent by %s", call.TypeName, call.FuncName))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
variants = append(variants, requestVariant{FuncName: call.FuncName, Transport: call.Transport, Fields: fields})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return append(errs, compareVariants(params, variants)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// compareVariants returns differences between platform parameters and all requests SDK sends to the path
|
||||||
|
func compareVariants(params []platformParam, variants []requestVariant) []string {
|
||||||
|
var errs []string
|
||||||
|
seenErr := make(map[string]bool)
|
||||||
|
add := func(msg string) {
|
||||||
|
if !seenErr[msg] {
|
||||||
|
seenErr[msg] = true
|
||||||
|
errs = append(errs, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byName := make([]map[string]sentField, len(variants))
|
||||||
|
for i, v := range variants {
|
||||||
|
byName[i] = make(map[string]sentField, len(v.Fields))
|
||||||
|
for _, f := range v.Fields {
|
||||||
|
if _, ok := byName[i][f.Name]; ok && v.Transport == transportForm {
|
||||||
|
add(fmt.Sprintf("Golang structure sends field %s more than once", f.Name))
|
||||||
|
}
|
||||||
|
byName[i][f.Name] = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paramsByName := make(map[string]bool, len(params))
|
||||||
|
for _, p := range params {
|
||||||
|
paramsByName[p.Name] = true
|
||||||
|
|
||||||
|
var sentBy, notSentBy []string
|
||||||
|
for i, v := range variants {
|
||||||
|
f, ok := byName[i][p.Name]
|
||||||
|
if !ok {
|
||||||
|
notSentBy = append(notSentBy, v.FuncName)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sentBy = append(sentBy, v.FuncName)
|
||||||
|
|
||||||
|
if !checkKind(p.Type, p.Items, f, v.Transport) {
|
||||||
|
add(fmt.Sprintf("Field %s has different type parameters on the platform (%s) and in golang structure (%s)",
|
||||||
|
p.Name, platformTypeString(p), f.Type))
|
||||||
|
}
|
||||||
|
if msg := checkRequired(p, f); msg != "" {
|
||||||
|
add(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(sentBy) == 0 {
|
||||||
|
add(fmt.Sprintf("Platform has field %s that golang structure doesn't", p.Name))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, fn := range notSentBy {
|
||||||
|
if p.Required {
|
||||||
|
add(fmt.Sprintf("Required field %s is not sent by %s", p.Name, fn))
|
||||||
|
} else if p.Type == "boolean" && p.Default == true {
|
||||||
|
add(fmt.Sprintf("Field %s is not sent by %s, platform default is true", p.Name, fn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range variants {
|
||||||
|
for _, f := range v.Fields {
|
||||||
|
if !paramsByName[f.Name] {
|
||||||
|
add(fmt.Sprintf("Golang structure has field %q (%s) that platform doesn't", f.Name, f.GoName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
func platformTypeString(p platformParam) string {
|
||||||
|
if p.Type == "array" && p.Items != "" {
|
||||||
|
return "array of " + p.Items
|
||||||
|
}
|
||||||
|
return p.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// hasValidateTag checks if `validate` tag contains exactly the given tag
|
||||||
|
func hasValidateTag(validate, tag string) bool {
|
||||||
|
for _, v := range strings.Split(validate, ",") {
|
||||||
|
if strings.TrimSpace(v) == tag {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkKind checks if type field from platform has the same value as field type in golang structure
|
func isIntKind(k reflect.Kind) bool {
|
||||||
func checkKind(platformType, items string, typ reflect.Type) bool {
|
switch k {
|
||||||
//nolint
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||||
switch typ.Kind() {
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint64, reflect.Uint16, reflect.Uint32, reflect.Uint8:
|
return true
|
||||||
if platformType == "integer" {
|
}
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
|
|
||||||
case reflect.String:
|
// checkRequired returns description of required mismatch between platform and golang field or empty string
|
||||||
|
func checkRequired(p platformParam, f sentField) string {
|
||||||
|
// validators without omitempty fail on zero value, so such field can not be omitted either
|
||||||
|
goRequired := hasValidateTag(f.Validate, "required") ||
|
||||||
|
(f.Validate != "" && !hasValidateTag(f.Validate, "omitempty"))
|
||||||
|
|
||||||
|
// numbers and booleans without omitempty are always sent and zero is a meaningful value for them
|
||||||
|
alwaysSent := false
|
||||||
|
if f.Type != nil && !f.OmitEmpty {
|
||||||
|
kind := f.Type.Kind()
|
||||||
|
alwaysSent = isIntKind(kind) || kind == reflect.Bool || kind == reflect.Float32 || kind == reflect.Float64
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Required && !goRequired && !alwaysSent {
|
||||||
|
return fmt.Sprintf("Field %s is required on the platform but is optional in golang structure", p.Name)
|
||||||
|
}
|
||||||
|
if !p.Required && hasValidateTag(f.Validate, "required") {
|
||||||
|
return fmt.Sprintf("Field %s is optional on the platform but is required in golang structure", p.Name)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkKind checks if type field from platform corresponds to field type in golang structure
|
||||||
|
func checkKind(platformType, items string, f sentField, transport string) bool {
|
||||||
|
typ := f.Type
|
||||||
|
// type can not be resolved on one of the sides
|
||||||
|
if typ == nil || platformType == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
kind := typ.Kind()
|
||||||
|
switch {
|
||||||
|
case isIntKind(kind):
|
||||||
|
return platformType == "integer"
|
||||||
|
|
||||||
|
case kind == reflect.String:
|
||||||
if platformType == "string" {
|
if platformType == "string" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
// json-encoded object or array of objects
|
||||||
|
return transport == transportForm &&
|
||||||
|
(platformType == "object" || (platformType == "array" && items == "object"))
|
||||||
|
|
||||||
case reflect.Bool:
|
case kind == reflect.Bool:
|
||||||
if platformType == "boolean" {
|
return platformType == "boolean"
|
||||||
return true
|
|
||||||
|
case kind == reflect.Float32 || kind == reflect.Float64:
|
||||||
|
return platformType == "number"
|
||||||
|
|
||||||
|
case kind == reflect.Interface:
|
||||||
|
if hasValidateTag(f.Validate, "isBool") {
|
||||||
|
return platformType == "boolean"
|
||||||
}
|
}
|
||||||
return false
|
return true
|
||||||
|
|
||||||
case reflect.Float32, reflect.Float64:
|
case kind == reflect.Map || kind == reflect.Struct:
|
||||||
if platformType == "number" {
|
return platformType == "object"
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
|
|
||||||
case reflect.Array, reflect.Slice:
|
case kind == reflect.Array || kind == reflect.Slice:
|
||||||
if platformType != "array" {
|
if platformType != "array" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
elem := typ.Elem()
|
elem := typ.Elem()
|
||||||
switch elem.Kind() {
|
for elem.Kind() == reflect.Ptr {
|
||||||
case reflect.String:
|
elem = elem.Elem()
|
||||||
if items == "string" {
|
}
|
||||||
return true
|
// items type is not declared on the platform
|
||||||
}
|
if items == "" {
|
||||||
return false
|
return true
|
||||||
|
}
|
||||||
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Int8, reflect.Int16, reflect.Uint, reflect.Uint64, reflect.Uint16, reflect.Uint32, reflect.Uint8:
|
switch {
|
||||||
if items == "integer" {
|
case elem.Kind() == reflect.String:
|
||||||
return true
|
// list of json-encoded objects
|
||||||
}
|
return items == "string" || (transport == transportForm && items == "object")
|
||||||
return false
|
case isIntKind(elem.Kind()):
|
||||||
|
return items == "integer"
|
||||||
default: // for cases like dataDisks etc.
|
case elem.Kind() == reflect.Bool:
|
||||||
return true
|
return items == "boolean"
|
||||||
|
case elem.Kind() == reflect.Float32 || elem.Kind() == reflect.Float64:
|
||||||
|
return items == "number"
|
||||||
|
case elem.Kind() == reflect.Struct || elem.Kind() == reflect.Map:
|
||||||
|
return items == "object"
|
||||||
|
default:
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // for cases like drivers etc
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user