main v1.12.2
asteam 2 weeks ago
parent e10ee7f801
commit 825b1a0a00

@ -1,27 +1,183 @@
## Version 1.12.1 ## Version 1.12.2
### Добавлено ### Добавлено
#### общие изменения
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-525 | Поддержка работы с различными сontent-type |
| BGOS-514 | Пакет SDN со структурой для SDN запросов |
| BGOS-587 | Проверка срока действия и обновления JWT токена для `DecortClient`, в связи с добавлением срока действия токена |
#### account #### account
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-559 | В структуру ответа `RecordACL` добавлено поле `Emails` в cloudapi/account | | BGOS-572 | Поля `StoragePolicyIDs` в структуре ответа `RecordAccount` в cloudapi/account и в `InfoAccount` cloudbroker/account |
| BGOS-572 | Поля `StoragePolicies` в структуре ответа `ResourceLimits` в cloudapi/account и в cloudbroker/account |
| BGOS-572 | Методы `AddStoragePolicy`, `DelStoragePolicyRequest` и структуры запросов `AddStoragePolicyRequest`, `DelStoragePolicyRequest` в cloudbroker/account |
| BGOS-572 | Обязательное поле `StoragePolicies` в структуру запроса `CreateRequest` в cloudbroker/account |
| BGOS-572 | Опциональное поле `StoragePolicies` в структуру запроса `UpdateRequest` в cloudbroker/account |
| BGOS-585 | Опциональное поле `ZoneID` в структуру запроса `ListRequest` в cloudapi/account и в cloudbroker/account |
#### audit
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-595 | Поле `CorrelationID` в структуры ответа `RecordAudit` в cloudapi/audit и в `RecordAudit` и `ItemAudit` в cloudbroker/audit |
#### bservice
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-576 | Опциональное поле `StoragePolicyID` в структуру запроса `GroupAddRequest` в cloudapi/bservice и в структуру запроса `GroupAddRequest` в cloudbroker/bservice |
| BGOS-585 | Опциональное поле `ZoneID` в структуру запроса `ListRequest` в cloudapi/bservice и в cloudbroker/bservice |
#### compute #### compute
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-566 | Поле `TrunkTags` в структуру `ItemVNFInterface` в структуре ответа `RecordCompute` в cloudapi/compute и в структуру `ItemInterface` в структуре ответа `RecordCompute` в cloudbroker/compute | | BGOS-569 | Опциональные поля `TimestampAT`, `TimestampTO`, `User`, `Call`, `SortBy`, `Page`, `Size`, `MinStatusCode`, `MaxStatusCode` в структуру запроса `AuditsRequest` в cloudapi/compute и в cloudbroker/compute |
| BGOS-492 | Метод `MigrateAbort` и структура запроса `MigrateAbortRequest` в cloudbroker/compute | | BGOS-575 | Обязательное поле `StoragePolicyID` в структуру запроса `CreateTemplateFromBlankRequest`, `DiskAddRequest`, `RedeployRequest` в cloudapi/compute и в cloudbroker/compute |
| BGOS-575 | Поле `StoragePolicyID` в структуру ответа `ItemComputeDisk` в cloudapi/compute и в структуру ответа `ItemDisk` в cloudbroker/compute |
| BGOS-580 | Поле `ZoneID` в структуру ответа `ItemCompute` в cloudapi/compute |
| BGOS-583 | Опциональные поля `SecGroups`, `EnableSecGroups` в структуру запроса `NetAttachRequest` в cloudapi/compute и в cloudbroker/compute |
| BGOS-583 | Поля `SecGroups`, `EnableSecGroups` в структуру ответа `ItemVNFInterface` в cloudapi/compute и в `ItemInterface` cloudbroker/compute |
| BGOS-585 | Опциональное поле `ZoneID` в структуру запроса `ListRequest` в cloudapi/compute и в cloudbroker/compute |
| BGOS-592 | Опциональное поле `Enabled` в структуру запроса `NetAttachRequest` в cloudapi/compute и в cloudbroker/compute |
| BGOS-593 | Поле `ToClean` в структурах ответа `ItemComputeDisk` в cloudapi/compute и `ItemDisk` cloudbroker/compute |
#### disks
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-574 | Поля `StoragePolicyID` в структуры ответа `RecordDisk` и `ItemDisk` в cloudapi/disks и в `InfoDisk` cloudbroker/disks |
| BGOS-574 | Метод `ChangeDiskStoragePolicy` и структура запроса `ChangeDiskStoragePolicyRequest` в cloudapi/disks и в cloudbroker/disks |
| BGOS-574 | Обязательное поле `StoragePolicyID` в структуры запроса `CreateRequest` и `ReplicateRequest` в cloudapi/disks и в cloudbroker/disks |
| BGOS-593 | Поле `ToClean` в структурах ответа `ItemDisk`, `RecordDisk` в cloudapi/disks и `InfoDisk` cloudbroker/disks |
#### dpdknet
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-584 | Опциональное поле `EnableSecGroups` в структуру запроса `UpdateRequest` в cloudbroker/dpdknet |
| BGOS-584 | Поле `EnableSecGroups` в структуры ответа `ItemDPDKNet`, `RecordDPDKNet` в cloudapi/dpdknet и в cloudbroker/dpdknet |
#### extnet
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-585 | Опциональное поле `ZoneID` в структуру запроса `ListRequest` в cloudapi/extnet и в cloudbroker/extnet |
| BGOS-584 | Опциональное поле `EnableSecGroups` в структуру запроса `UpdateRequest` в cloudbroker/extnet |
| BGOS-584 | Поле `EnableSecGroups` в структуру ответа `ItemExtNet` в cloudbroker/extnet |
| BGOS-584 | Поле `EnableSecGroups` в структуру ответа `RecordExtNet` в cloudapi/extnet и в cloudbroker/extnet |
#### image
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-578 | Обязательное поле `StoragePolicyID` в структуру запроса `CreateRequest` в cloudapi/image и в структуры запроса `CreateRequest` и `CreateCDROMImageRequest` в cloudbroker/image |
| BGOS-578 | Поле `StoragePolicyID` в структуру ответа `RecordImage` в cloudapi/image и в структуры ответа `RecordImage` и `ItemImage` в cloudbroker/image |
| BGOS-578 | Метод `ChangeStoragePolicy` и структура запроса `ChangeStoragePolicyRequest` в cloudapi/image и в cloudbroker/image |
#### k8s
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-577 | Обязательное поле `StoragePolicyID` в структуры запроса `CreateRequest` и `WorkersGroupAddRequest` в cloudapi/k8s и в структуры запроса `CreateRequest` и `WorkersGroupAddRequest` в cloudbroker/k8s |
| BGOS-585 | Опциональное поле `ZoneID` в структуру запроса `ListRequest` в cloudapi/k8s и в cloudbroker/k8s |
#### kvmx86
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-575 | Обязательное поле `StoragePolicyID` в структуры запросов `CreateRequest`, `DataDisk`, `CreateBlankRequest` в cloudapi/kvmx86 и cloudbroker/kvmx86 и `MassCreateRequest` в cloudbroker/kvmx86 |
| BGOS-583 | Опциональные поля `SecGroups`, `EnableSecGroups` в структуру запроса `Interface` в cloudapi/kvmx86 и в cloudbroker/kvmx86 |
| BGOS-592 | Опциональное поле `Enabled` в структуру запроса `Interface` в cloudapi/kvmx86 и в cloudbroker/kvmx86 |
#### lb
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-585 | Опциональное поле `ZoneID` в структуру запроса `ListRequest` в cloudapi/lb и в cloudbroker/lb |
#### node
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-597 | Поле `VCPU` в структуру ответа `FreeResourcesInfo` в cloudbroker/node |
#### rg
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-573 | Поля `StoragePolicyIDs` в структуре ответа `RecordResourceGroup` в cloudapi/rg и в `ItemRG` cloudbroker/rg |
| BGOS-573 | Поля `StoragePolicies` в структуре ответа `ResourceLimits` в cloudapi/rg и в cloudbroker/rg |
| BGOS-573 | Методы `AddStoragePolicy`, `DelStoragePolicyRequest` и структуры запросов `AddStoragePolicyRequest`, `DelStoragePolicyRequest` в cloudbroker/rg |
| BGOS-573 | Опциональное поле `StoragePolicies` в структуры запроса `CreateRequest`, `UpdateRequest` в cloudapi/rg и в cloudbroker/rg |
#### security group
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-582 | Группа ручек `security_group` в cloudapi и в cloudbroker |
#### storage policy
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-571 | Группа ручек `storage_policy` в cloudapi и в cloudbroker |
#### trunk
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-565 | Опциональное поле `Status` в структуру запроса `ListRequest` в cloudapi/trunk и в cloudbroker/trunk |
#### user
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-562 | Опциональное поле `AccountID` в структуру запроса `CreateVirtualRequest` в cloudapi/image и в cloudbroker/image |
#### vins
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-584 | Метод `Update` и структура запроса `UpdateRequest` в cloudbroker/vins |
| BGOS-584 | Поле `EnableSecGroups` в структуру ответа `ItemVINS` в cloudbroker/vins |
| BGOS-584 | Поле `EnableSecGroups` в структуру ответа `RecordVINS` в cloudapi/vins и в cloudbroker/vins |
#### SDN access groups
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-514 | Группа api access_groups |
### Исправлено ### Исправлено
#### accounts #### compute
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-559 | Структура ответа `ItemAccount` использует структуру `ListRecordACL` в поле `ACL` в cloudapi/account | | BGOS-569 | Изменена структура ответа с `ListAudits` на `*ListAudits`, содержащую поля `Data` и `EntryCount` в методе `Audits` в cloudapi/compute |
| BGOS-569 | Изменена структура ответа с `ListDetailedAudits` на `*ListDetailedAudits`, содержащую поля `Data` и `EntryCount` в методе `Audits` в cloudbroker/compute |
#### user
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-561 | Изменен тип поля `UserIDs` с stirng на []string в структуре запроса `DeleteUsersRequest` в cloudbroker/user |
#### vins
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-560 | Изменен тип возвращаемого значения методов `MassDelete`, `MassDisable`, `MassEnable` c bool на string в cloudbroker/vins|
### Удалено
#### disks
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-563 | Опциональное поле `Drivers` в структуре запроса `FromPlatformDiskRequest` в cloudapi/disks и cloudbroker/disks |
#### compute
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-580 | Поле `ZoneID` в структуре ответа `ItemComputeDisk` в cloudapi/compute |
#### image #### image
| Идентификатор<br>задачи | Описание | | Идентификатор<br>задачи | Описание |
| --- | --- | | --- | --- |
| BGOS-564 | Загрузка образов в cloudbroker/image | | BGOS-563 | Опциональное поле `Drivers` в структуре запроса `CreateRequest` в cloudapi/image и cloudbroker/image |
| BGOS-563 | Опциональное поле `Drivers` в структуре запроса `CreateCDROMImageRequest` в cloudbroker/image |
#### k8ci
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-563 | Опциональные поля `MasterDriver` и `WorkerDriver` в структурах запроса `ListRequest` и `ListDeletedRequest` в cloudapi/k8ci и cloudbroker/k8ci |
| BGOS-563 | Опциональные поля `MasterDriver` и `WorkerDriver` в структуре запроса `CreateRequest` в cloudbroker/k8ci |
#### kvmx86
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BGOS-563 | Опциональное поле `Driver` в структурах запроса `CreateRequest` и `CreateBlankRequest` в cloudapi/kvmx86 и cloudbroker/kvmx86 |

@ -1,6 +1,3 @@
# Внимание
Данная версия предназначена только для версии платформы 4.4.0 build 963!
# Decort SDK # Decort SDK
Decort SDK - это библиотека, написанная на языке GO, позволяющая взаимодействовать с API облачной платформы **DECORT**. Библиотека содержит в себе структуры и методы, необходимые для отправки запросов. Decort SDK имеет встроенный http-клиент и поддерживает разные способы авторизации на платформе. Библиотека так же содержит в себе модели ответов от платформы. Decort SDK - это библиотека, написанная на языке GO, позволяющая взаимодействовать с API облачной платформы **DECORT**. Библиотека содержит в себе структуры и методы, необходимые для отправки запросов. Decort SDK имеет встроенный http-клиент и поддерживает разные способы авторизации на платформе. Библиотека так же содержит в себе модели ответов от платформы.
@ -100,6 +97,7 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
- `cloudapi` - пользовательская группа, которая позволяет воспользоваться всем стардартным функционалом платформы; - `cloudapi` - пользовательская группа, которая позволяет воспользоваться всем стардартным функционалом платформы;
- `cloudbroker` - административная группа, которая позволяет воспользоваться всем стандартным функционалом платформы и расширенными возможностями, включающими в себя управление пользователями, ресурсами, платформами размещения ресурсов и т.д. - `cloudbroker` - административная группа, которая позволяет воспользоваться всем стандартным функционалом платформы и расширенными возможностями, включающими в себя управление пользователями, ресурсами, платформами размещения ресурсов и т.д.
- `sdn` - группа для работы с SDN;
### Cloudapi ### Cloudapi
@ -122,8 +120,10 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
- `Locations` - получение информации о grid площадки; - `Locations` - получение информации о grid площадки;
- `Prometheus` - получение статистики prometheus; - `Prometheus` - получение статистики prometheus;
- `RG` - управление ресурсными группами аккаунта; - `RG` - управление ресурсными группами аккаунта;
- `Security group` управление группами безопасности;
- `SEP` - управление storage endpoint (sep); - `SEP` - управление storage endpoint (sep);
- `Stack` - получение информации о вычислительных узлах; - `Stack` - получение информации о вычислительных узлах;
- `Storage policy` получение информации о политиках хранения;
- `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера); - `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера);
- `Trunk` - получение информации о транковых портах; - `Trunk` - получение информации о транковых портах;
- `VFPool` - управление пулом виртуальных сетевых функций; - `VFPool` - управление пулом виртуальных сетевых функций;
@ -157,8 +157,10 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
- `Prometheus` - получение статистики prometheus; - `Prometheus` - получение статистики prometheus;
- `Resmon` - получение статистики resource monitoring; - `Resmon` - получение статистики resource monitoring;
- `RG` - управление ресурсными группами аккаунта; - `RG` - управление ресурсными группами аккаунта;
- `Security group` управление группами безопасности;
- `SEP` - управление storage endpoint (sep); - `SEP` - управление storage endpoint (sep);
- `Stack` - получение информации о вычислительных узлах; - `Stack` - получение информации о вычислительных узлах;
- `Storage policy` управление политиками хранения;
- `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера); - `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера);
- `Trunk` - управление транковыми портами; - `Trunk` - управление транковыми портами;
- `User` - управление пользователями (индивидуально); - `User` - управление пользователями (индивидуально);
@ -167,6 +169,13 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
- `VINS` - управление виртуальными изолированными сетями. - `VINS` - управление виртуальными изолированными сетями.
- `Zone` - управление зонами. - `Zone` - управление зонами.
### SDN
`SDN` позволяет выполнять запросы к группе пользовательских конечных точек
Данная группа ручек позволяет выполнять следующие операции в платформе:
- `AccessGroup` - управление группами доступа
## Работа с библиотекой ## Работа с библиотекой
Алгоритм работы с библиотекой выглядит следующим образом: Алгоритм работы с библиотекой выглядит следующим образом:
@ -293,6 +302,7 @@ func main() {
- `pkg/cloudapi` - для `cloudapi` - `pkg/cloudapi` - для `cloudapi`
- `pkg/cloudbroker` - для `cloudbroker` - `pkg/cloudbroker` - для `cloudbroker`
- `pkg/sdn` - для `sdn`
В каждом пакете находятся пакеты групп API: В каждом пакете находятся пакеты групп API:
@ -313,8 +323,10 @@ func main() {
- `pkg/cloudapi/locations` - для `Locations` - `pkg/cloudapi/locations` - для `Locations`
- `pkg/cloudapi/prometheus` - для `Prometheus` - `pkg/cloudapi/prometheus` - для `Prometheus`
- `pkg/cloudapi/rg` - для `RG` - `pkg/cloudapi/rg` - для `RG`
- `pkg/cloudapi/security_group` - для `Security group`
- `pkg/cloudapi/sep` - для `SEP` - `pkg/cloudapi/sep` - для `SEP`
- `pkg/cloudapi/stack` - для `Stack` - `pkg/cloudapi/stack` - для `Stack`
- `pkg/cloudapi/storage_policy` - для `Storage policy`
- `pkg/cloudapi/tasks` - для `Tasks` - `pkg/cloudapi/tasks` - для `Tasks`
- `pkg/cloudapi/trunk` - для `Trunk` - `pkg/cloudapi/trunk` - для `Trunk`
- `pkg/cloudapi/vfpool` - для `VFPool` - `pkg/cloudapi/vfpool` - для `VFPool`
@ -343,8 +355,10 @@ func main() {
- `pkg/cloudbroker/prometheus` - для `Prometheus` - `pkg/cloudbroker/prometheus` - для `Prometheus`
- `pkg/cloudbroker/resmon` - для `Resmon` - `pkg/cloudbroker/resmon` - для `Resmon`
- `pkg/cloudbroker/rg` - для `RG` - `pkg/cloudbroker/rg` - для `RG`
- `pkg/cloudbroker/security_group` - для `Security group`
- `pkg/cloudbroker/sep` - для `SEP` - `pkg/cloudbroker/sep` - для `SEP`
- `pkg/cloudbroker/stack` - для `Stack` - `pkg/cloudbroker/stack` - для `Stack`
- `pkg/cloudbroker/storage_policy` - для `Storage policy`
- `pkg/cloudbroker/tasks` - для `Tasks` - `pkg/cloudbroker/tasks` - для `Tasks`
- `pkg/cloudbroker/trunk` - для `Trunk` - `pkg/cloudbroker/trunk` - для `Trunk`
- `pkg/cloudbroker/user` - для `User` - `pkg/cloudbroker/user` - для `User`
@ -352,6 +366,8 @@ func main() {
- `pkg/cloudbroker/vfpool` - для `VFPool` - `pkg/cloudbroker/vfpool` - для `VFPool`
- `pkg/cloudbroker/vins` - для `VINS` - `pkg/cloudbroker/vins` - для `VINS`
- `pkg/cloudbroker/zone` - для `Zone` - `pkg/cloudbroker/zone` - для `Zone`
- **sdn**:
- `pkg/sdn/access_groups` - для `AccessGroups`
Все поля структуры имеют описание, в которых содержится: Все поля структуры имеют описание, в которых содержится:
@ -485,7 +501,7 @@ func main() {
Чтобы выполнить запрос, необходимо: Чтобы выполнить запрос, необходимо:
1. Вызвать у клиента метод, отвечаеющий за определение группы API для взаимодействия, это может быть `.CloudAPI()`, либо `.CloudBroker()`. Данные методы возвращаеют соответствующие структуры, с помощью которых можно совершать запросы. 1. Вызвать у клиента метод, отвечающий за определение группы API для взаимодействия, это может быть `.CloudAPI()`, `.CloudBroker()` или `.SDN()`. Данные методы возвращают соответствующие структуры, с помощью которых можно совершать запросы.
2. Вызвать у возвращенной структуры метод, определяющий группу ручек для взаимодействия. 2. Вызвать у возвращенной структуры метод, определяющий группу ручек для взаимодействия.
Доступные методы для `.CloudAPI()`: Доступные методы для `.CloudAPI()`:
@ -506,8 +522,10 @@ func main() {
- `.Locations()` - для работы с `Locations` - `.Locations()` - для работы с `Locations`
- `.Prometheus()` - для работы с `Prometheus` - `.Prometheus()` - для работы с `Prometheus`
- `.RG()` - для работы с `RG` - `.RG()` - для работы с `RG`
- `.SecurityGroup()` - для работы с `Security Group`
- `.SEP()` - для работы с `SEP` - `.SEP()` - для работы с `SEP`
- `.Stack()` - для работы с `Stack` - `.Stack()` - для работы с `Stack`
- `.StoragePolicy()` - для работы с `Storage Policy`
- `.Tasks()` - для работы с `Tasks` - `.Tasks()` - для работы с `Tasks`
- `.Trunk()` - для работы с `Trunk` - `.Trunk()` - для работы с `Trunk`
- `.VFPool()` - для работы с `VFPool` - `.VFPool()` - для работы с `VFPool`
@ -538,8 +556,10 @@ func main() {
- `.Prometheus()` - для работы с `Prometheus` - `.Prometheus()` - для работы с `Prometheus`
- `.Resmon()` - для работы с `Resmon` - `.Resmon()` - для работы с `Resmon`
- `.RG()` - для работы с `RG` - `.RG()` - для работы с `RG`
- `.SecurityGroup()` - для работы с `Security Group`
- `.SEP()` - для работы с `SEP` - `.SEP()` - для работы с `SEP`
- `.Stack()` - для работы с `Stack` - `.Stack()` - для работы с `Stack`
- `.StoragePolicy()` - для работы с `Storage Policy`
- `.Tasks()` - для работы с `Tasks` - `.Tasks()` - для работы с `Tasks`
- `.Trunk()` - для работы с `Trunk` - `.Trunk()` - для работы с `Trunk`
- `.User()` - для работы с `User` - `.User()` - для работы с `User`
@ -548,6 +568,10 @@ func main() {
- `.VINS()` - для работы с `VINS` - `.VINS()` - для работы с `VINS`
- `.Zone()` - для работы с `Zone` - `.Zone()` - для работы с `Zone`
Доступные методы для `.SDN()`:
- `.AccessGroup()` - для работы с `AccessGroup`
3. Вызвать метод, отвечающий за выполнение запроса и передать в него: 3. Вызвать метод, отвечающий за выполнение запроса и передать в него:
- контекст; - контекст;

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
@ -21,6 +22,7 @@ import (
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker" "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn"
) )
// DecortClient is HTTP-client for platform // DecortClient is HTTP-client for platform
@ -38,12 +40,6 @@ func New(cfg config.Config) *DecortClient {
cfg.Retries = 5 cfg.Retries = 5
} }
var expiryTime time.Time
if cfg.Token != "" {
expiryTime = time.Now().AddDate(0, 0, 1)
}
return &DecortClient{ return &DecortClient{
decortURL: cfg.DecortURL, decortURL: cfg.DecortURL,
client: &http.Client{ client: &http.Client{
@ -54,9 +50,8 @@ func New(cfg config.Config) *DecortClient {
}, },
}, },
}, },
cfg: trimConfig(&cfg), cfg: trimConfig(&cfg),
expiryTime: expiryTime, mutex: &sync.Mutex{},
mutex: &sync.Mutex{},
} }
} }
@ -70,6 +65,11 @@ func (dc *DecortClient) CloudBroker() *cloudbroker.CloudBroker {
return cloudbroker.New(dc) return cloudbroker.New(dc)
} }
// SDN builder
func (dc *DecortClient) SDN() *sdn.SDN {
return sdn.New(dc)
}
// DecortApiCall method for sending requests to the platform // DecortApiCall method for sending requests to the platform
func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) { func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
@ -107,6 +107,47 @@ func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, p
return respBytes, err return respBytes, err
} }
// DecortApiCallCtype method for sending requests to the platform with content type
func (dc *DecortClient) DecortApiCallCtype(ctx context.Context, method, url, ctype string, params interface{}) ([]byte, error) {
var body *bytes.Buffer
switch ctype {
case constants.MIMESTREAM:
body = bytes.NewBuffer(params.([]byte))
case constants.MIMEJSON:
jsonBody, err := json.Marshal(params)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(jsonBody)
default:
ctype = constants.MIMEPOSTForm
values, err := query.Values(params)
if err != nil {
return nil, err
}
body = bytes.NewBufferString(values.Encode())
}
req, err := http.NewRequestWithContext(ctx, method, dc.decortURL+constants.RESTMACHINE+url, body)
if err != nil {
return nil, err
}
// get token
if err = dc.getToken(ctx); err != nil {
return nil, err
}
// perform request
respBytes, err := dc.do(req, ctype)
if err != nil {
return nil, err
}
return respBytes, err
}
// DecortApiCallMP method for sending requests to the platform // DecortApiCallMP method for sending requests to the platform
func (dc *DecortClient) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) { func (dc *DecortClient) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
body, ctype, err := multiPartReq(params) body, ctype, err := multiPartReq(params)
@ -170,8 +211,13 @@ func (dc *DecortClient) getToken(ctx context.Context) error {
// save token in config // save token in config
token := string(tokenBytes) token := string(tokenBytes)
expiryTime, err := getTokenExp(token)
if err != nil {
return fmt.Errorf("cannot get expiry time: %w", err)
}
dc.cfg.Token = token dc.cfg.Token = token
dc.expiryTime = time.Now().AddDate(0, 0, 1) dc.expiryTime = expiryTime
return nil return nil
} }
@ -375,3 +421,29 @@ func trimConfig(cfg *config.Config) config.Config {
cfg.DecortURL = strings.TrimSuffix(cfg.DecortURL, "/") cfg.DecortURL = strings.TrimSuffix(cfg.DecortURL, "/")
return *cfg return *cfg
} }
func getTokenExp(token string) (time.Time, error) {
parts := strings.Split(token, ".")
if len(parts) != 3 {
return time.Time{}, fmt.Errorf("invalid token format")
}
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return time.Time{}, fmt.Errorf("error decode payload from token: %w", err)
}
var claims map[string]interface{}
if err := json.Unmarshal(payload, &claims); err != nil {
return time.Time{}, err
}
exp, ok := claims["exp"]
if !ok {
return time.Time{}, fmt.Errorf("exp time bot found")
}
expTime := time.Unix(int64(exp.(float64)), 0)
return expTime, nil
}

@ -131,6 +131,72 @@ func (bdc *BVSDecortClient) DecortApiCall(ctx context.Context, method, url strin
return respBytes, err return respBytes, err
} }
// DecortApiCallCtype method for sending requests to the platform with content type
func (bdc *BVSDecortClient) DecortApiCallCtype(ctx context.Context, method, url, ctype string, params interface{}) ([]byte, error) {
var body *bytes.Buffer
switch ctype {
case constants.MIMESTREAM:
body = bytes.NewBuffer(params.([]byte))
case constants.MIMEJSON:
jsonBody, err := json.Marshal(params)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(jsonBody)
default:
ctype = constants.MIMEPOSTForm
values, err := query.Values(params)
if err != nil {
return nil, err
}
body = bytes.NewBufferString(values.Encode())
}
req, err := http.NewRequestWithContext(ctx, method, bdc.decortURL+constants.RESTMACHINE+url, body)
if err != nil {
return nil, err
}
// get token
if bdc.cfg.Token.AccessToken == "" {
if _, err = bdc.GetToken(ctx); err != nil {
return nil, err
}
}
// refresh token
if bdc.cfg.Token.RefreshToken != "" && bdc.cfg.Token.Expiry.Add(-time.Duration(bdc.cfg.TimeToRefresh)*time.Minute).Before(time.Now()) {
if _, err := bdc.RefreshToken(ctx); err != nil {
if _, err = bdc.GetToken(ctx); err != nil {
return nil, err
}
}
}
// perform request
reqCopy := req.Clone(ctx)
respBytes, err := bdc.do(req, ctype)
if err == nil {
return respBytes, nil
}
// get token and retry in case of access denied
if err.Error() == "access is denied" {
_, err = bdc.GetToken(ctx)
if err != nil {
return nil, err
}
respBytes, err = bdc.do(reqCopy, "")
if err != nil {
return nil, err
}
}
return respBytes, err
}
func (bdc *BVSDecortClient) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) { func (bdc *BVSDecortClient) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
body, ctype, err := multiPartReq(params) body, ctype, err := multiPartReq(params)
if err != nil { if err != nil {

@ -7,6 +7,9 @@ type Caller interface {
// DecortApiCall method for sending requests to the platform // DecortApiCall method for sending requests to the platform
DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error)
// DecortApiCallCtype method for sending requests to the platform
DecortApiCallCtype(ctx context.Context, method, url, ctype string, params interface{}) ([]byte, error)
// DecortApiCallMP method for sending requests to the platform // DecortApiCallMP method for sending requests to the platform
DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error)
} }

@ -2,9 +2,23 @@ package constants
const ( const (
RESTMACHINE = "/restmachine" RESTMACHINE = "/restmachine"
)
// RAM_DIVISIBILITY sets divisibility of RAM value const (
RAM_DIVISIBILITY uint64 = 128 MIMEJSON = "application/json"
MIMEHTML = "text/html"
MIMEXML = "application/xml"
MIMEXML2 = "text/xml"
MIMEPlain = "text/plain"
MIMEPOSTForm = "application/x-www-form-urlencoded"
MIMEMultipartPOSTForm = "multipart/form-data"
MIMEPROTOBUF = "application/x-protobuf"
MIMEMSGPACK = "application/x-msgpack"
MIMEMSGPACK2 = "application/msgpack"
MIMEYAML = "application/x-yaml"
MIMEYAML2 = "application/yaml"
MIMETOML = "application/toml"
MIMESTREAM = "application/octet-stream"
) )
var FileName = map[string]string{ var FileName = map[string]string{

@ -14,13 +14,6 @@ import (
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/multierror" "repository.basistech.ru/BASIS/decort-golang-sdk/internal/multierror"
) )
// computeDriverValidator is used to validate Driver field in kvmx86 create.
func computeDriverValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, computeDriverValues)
}
// protoValidator is used to validate Proto fields. // protoValidator is used to validate Proto fields.
func protoValidator(fe validator.FieldLevel) bool { func protoValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String() fieldValue := fe.Field().String()
@ -58,13 +51,6 @@ func resTypesValidator(fe validator.FieldLevel) bool {
return true return true
} }
// driverValidator is used to validate Driver fields.
func driverValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, driverValues)
}
// accountCUTypeValidator is used to validate CUType field. // accountCUTypeValidator is used to validate CUType field.
func accountCUTypeValidator(fe validator.FieldLevel) bool { func accountCUTypeValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String() fieldValue := fe.Field().String()
@ -121,6 +107,27 @@ func computex86NetTypeValidator(fe validator.FieldLevel) bool {
return IsInSlice(fieldValue, computex86NetTypeValues) return IsInSlice(fieldValue, computex86NetTypeValues)
} }
// securityGroupDirectionValidator is used to validate Direction field
func securityGroupDirectionValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, securityGroupDirectionValues)
}
// securityGroupEthertypeValidator is used to validate Ethertype field
func securityGroupEthertypeValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, securityGroupEthertypeValues)
}
// securityGroupProtocolValidator is used to validate Protocol field
func securityGroupProtocolValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String()
return IsInSlice(fieldValue, securityGroupProtocolValues)
}
// computeOrderValidator is used to validate Order field. // computeOrderValidator is used to validate Order field.
func computeOrderValidator(fe validator.FieldLevel) bool { func computeOrderValidator(fe validator.FieldLevel) bool {
fieldSlice, ok := fe.Field().Interface().([]string) fieldSlice, ok := fe.Field().Interface().([]string)
@ -207,22 +214,6 @@ func imageTypeValidator(fe validator.FieldLevel) bool {
return IsInSlice(fieldValue, imageTypeValues) return IsInSlice(fieldValue, imageTypeValues)
} }
// imageDriversValidator is used to validate Drivers field.
func imageDriversValidator(fe validator.FieldLevel) bool {
fieldSlice, ok := fe.Field().Interface().([]string)
if !ok {
return false
}
for _, item := range fieldSlice {
if !IsInSlice(item, imageDriversValues) {
return false
}
}
return true
}
// imageArchitectureValidator is used to validate Architecture field. // imageArchitectureValidator is used to validate Architecture field.
func imageArchitectureValidator(fe validator.FieldLevel) bool { func imageArchitectureValidator(fe validator.FieldLevel) bool {
fieldValue := fe.Field().String() fieldValue := fe.Field().String()

@ -28,12 +28,6 @@ func errorMessage(fe validator.FieldError) string {
case "isBool": case "isBool":
return fmt.Sprintf("%s %s: must be bool type", prefix, fe.Field()) return fmt.Sprintf("%s %s: must be bool type", prefix, fe.Field())
case "driver":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(driverValues))
case "accessType": case "accessType":
return fmt.Sprintf("%s %s must be one of the following: %s", return fmt.Sprintf("%s %s must be one of the following: %s",
prefix, prefix,
@ -128,12 +122,6 @@ func errorMessage(fe validator.FieldError) string {
fe.Field(), fe.Field(),
joinValues(computeDataDisksValues)) joinValues(computeDataDisksValues))
case "computeDriver":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(computeDriverValues))
// Disk Validators // Disk Validators
case "diskType": case "diskType":
return fmt.Sprintf("%s %s must be one of the following: %s", return fmt.Sprintf("%s %s must be one of the following: %s",
@ -201,12 +189,6 @@ func errorMessage(fe validator.FieldError) string {
fe.Field(), fe.Field(),
joinValues(imageTypeValues)) joinValues(imageTypeValues))
case "imageDrivers":
return fmt.Sprintf("%s %s must contain only the following: %s",
prefix,
fe.Field(),
joinValues(imageDriversValues))
case "imageArchitecture": case "imageArchitecture":
return fmt.Sprintf("%s %s must be one of the following: %s", return fmt.Sprintf("%s %s must be one of the following: %s",
prefix, prefix,
@ -341,6 +323,25 @@ func errorMessage(fe validator.FieldError) string {
fe.Field(), fe.Field(),
joinValues(userProviders)) joinValues(userProviders))
// security group validators
case "securityGroupDirection":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(securityGroupDirectionValues))
case "securityGroupEthertype":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(securityGroupEthertypeValues))
case "securityGroupProtocol":
return fmt.Sprintf("%s %s must be one of the following: %s",
prefix,
fe.Field(),
joinValues(securityGroupProtocolValues))
// trunk tags validator // trunk tags validator
case "trunkTags": case "trunkTags":
return fmt.Sprintf("%s %s must be in range from 1 to 4095", return fmt.Sprintf("%s %s must be in range from 1 to 4095",

@ -31,11 +31,6 @@ func registerAllValidators(validate *validator.Validate) error {
return err return err
} }
err = validate.RegisterValidation("computeDriver", computeDriverValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("apiGroup", apiGroupValidator) err = validate.RegisterValidation("apiGroup", apiGroupValidator)
if err != nil { if err != nil {
return err return err
@ -51,11 +46,6 @@ func registerAllValidators(validate *validator.Validate) error {
return err return err
} }
err = validate.RegisterValidation("driver", driverValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("imageBootType", imageBootTypeValidator) err = validate.RegisterValidation("imageBootType", imageBootTypeValidator)
if err != nil { if err != nil {
return err return err
@ -66,11 +56,6 @@ func registerAllValidators(validate *validator.Validate) error {
return err return err
} }
err = validate.RegisterValidation("imageDrivers", imageDriversValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("imageArchitecture", imageArchitectureValidator) err = validate.RegisterValidation("imageArchitecture", imageArchitectureValidator)
if err != nil { if err != nil {
return err return err
@ -301,5 +286,20 @@ func registerAllValidators(validate *validator.Validate) error {
return err return err
} }
err = validate.RegisterValidation("securityGroupDirection", securityGroupDirectionValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("securityGroupEthertype", securityGroupEthertypeValidator)
if err != nil {
return err
}
err = validate.RegisterValidation("securityGroupProtocol", securityGroupProtocolValidator)
if err != nil {
return err
}
return nil return nil
} }

@ -3,7 +3,6 @@ package validators
var ( var (
apiGroupValues = []string{"cloudapi", "cloudbroker", "system"} apiGroupValues = []string{"cloudapi", "cloudbroker", "system"}
driverValues = []string{"KVM_X86"}
accessTypeValues = []string{"R", "RCX", "ARCXDU"} accessTypeValues = []string{"R", "RCX", "ARCXDU"}
resTypesValues = []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"} resTypesValues = []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}
protoValues = []string{"tcp", "udp"} protoValues = []string{"tcp", "udp"}
@ -20,7 +19,6 @@ var (
computex86NetTypeValues = []string{"EXTNET", "VINS", "VFNIC", "DPDK", "SDN", "EMPTY", "TRUNK"} computex86NetTypeValues = []string{"EXTNET", "VINS", "VFNIC", "DPDK", "SDN", "EMPTY", "TRUNK"}
computeOrderValues = []string{"cdrom", "network", "hd"} computeOrderValues = []string{"cdrom", "network", "hd"}
computeDataDisksValues = []string{"KEEP", "DETACH", "DESTROY"} computeDataDisksValues = []string{"KEEP", "DETACH", "DESTROY"}
computeDriverValues = []string{"KVM_X86"}
diskTypeValues = []string{"B", "T", "D"} diskTypeValues = []string{"B", "T", "D"}
@ -38,7 +36,6 @@ var (
imageBootTypeValues = []string{"uefi", "bios"} imageBootTypeValues = []string{"uefi", "bios"}
imageTypeValues = []string{"windows", "linux", "unknown"} imageTypeValues = []string{"windows", "linux", "unknown"}
imageDriversValues = []string{"KVM_X86"}
imageArchitectureValues = []string{"X86_64"} imageArchitectureValues = []string{"X86_64"}
sepFieldTypeValues = []string{"int", "str", "bool", "list", "dict"} sepFieldTypeValues = []string{"int", "str", "bool", "list", "dict"}
@ -76,6 +73,10 @@ var (
userProviders = []string{"bvs", "decs3o"} userProviders = []string{"bvs", "decs3o"}
deviceValues = []string{"primary", "secondary"} deviceValues = []string{"primary", "secondary"}
securityGroupDirectionValues = []string{"inbound", "outbound"}
securityGroupEthertypeValues = []string{"IPv4", "IPv6"}
securityGroupProtocolValues = []string{"icmp", "tcp", "udp"}
) )
const ( const (

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -102,6 +103,47 @@ func (ldc *LegacyDecortClient) DecortApiCall(ctx context.Context, method, url st
return respBytes, err return respBytes, err
} }
// DecortApiCallCtype method for sending requests to the platform with content type
func (ldc *LegacyDecortClient) DecortApiCallCtype(ctx context.Context, method, url, ctype string, params interface{}) ([]byte, error) {
// get token
if err := ldc.getToken(ctx); err != nil {
return nil, err
}
var body *bytes.Buffer
switch ctype {
case constants.MIMESTREAM:
body = bytes.NewBuffer(params.([]byte))
case constants.MIMEJSON:
jsonBody, err := json.Marshal(params)
if err != nil {
return nil, err
}
body = bytes.NewBuffer(jsonBody)
default:
ctype = constants.MIMEPOSTForm
values, err := query.Values(params)
if err != nil {
return nil, err
}
body = bytes.NewBufferString(values.Encode() + fmt.Sprintf("&authkey=%s", ldc.cfg.Token))
}
req, err := http.NewRequestWithContext(ctx, method, ldc.decortURL+constants.RESTMACHINE+url, body)
if err != nil {
return nil, err
}
// perform request
respBytes, err := ldc.do(req, ctype)
if err != nil {
return nil, err
}
return respBytes, err
}
func (ldc *LegacyDecortClient) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) { func (ldc *LegacyDecortClient) DecortApiCallMP(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
body, ctype, err := multiPartReq(params) body, ctype, err := multiPartReq(params)
if err != nil { if err != nil {

@ -30,6 +30,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -73,6 +73,15 @@ type ResourceLimits struct {
// Number of graphics cores // Number of graphics cores
GPUUnits float64 `json:"gpu_units"` GPUUnits float64 `json:"gpu_units"`
// Storage policy
StoragePolicy []StoragePolicyItem `json:"storage_policy"`
}
type StoragePolicyItem struct {
ID uint64 `json:"id"`
Limit int `json:"limit"`
} }
// Main information in one of if the list of accounts // Main information in one of if the list of accounts
@ -103,6 +112,9 @@ type ItemAccount struct {
// Updated time // Updated time
UpdatedTime uint64 `json:"updatedTime"` UpdatedTime uint64 `json:"updatedTime"`
// Zones
ZoneIDs []uint64 `json:"zoneIds"`
} }
// List of accounts // List of accounts
@ -275,6 +287,9 @@ type RecordAccount struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy ids
StoragePolicyIDs []uint64 `json:"storage_policy_ids"`
// UniqPools // UniqPools
UniqPools []interface{} `json:"uniqPools"` UniqPools []interface{} `json:"uniqPools"`
@ -291,7 +306,7 @@ type RecordAccount struct {
VINSes uint64 `json:"vinses"` VINSes uint64 `json:"vinses"`
// Zone // Zone
ZoneIDs []ZoneID ZoneIDs []ZoneID `json:"zoneIds"`
// Zones // Zones
DefaultZoneID uint64 `json:"defaultZoneId"` DefaultZoneID uint64 `json:"defaultZoneId"`

@ -12,6 +12,9 @@ type RecordAudit struct {
// GUID // GUID
GUID string `json:"guid"` GUID string `json:"guid"`
// Correlation ID
CorrelationID string `json:"correlation_id"`
// Kwargs // Kwargs
Kwargs string `json:"kwargs"` Kwargs string `json:"kwargs"`

@ -38,11 +38,9 @@ type GroupAddRequest struct {
// Required: true // Required: true
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"` ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
// Compute driver // Compute driver like a KVM_X86, etc.
// should be one of:
// - KVM_X86
// Required: true // Required: true
Driver string `url:"driver" json:"driver" validate:"driver"` Driver string `url:"driver" json:"driver" validate:"required"`
// Storage endpoint provider ID // Storage endpoint provider ID
// Required: false // Required: false
@ -75,6 +73,10 @@ type GroupAddRequest struct {
//Chipset "i440fx" or "Q35 //Chipset "i440fx" or "Q35
//Required: false //Required: false
Chipset string `url:"chipset,omitempty" json:"chipset,omitempty" validate:"chipset,omitempty"` Chipset string `url:"chipset,omitempty" json:"chipset,omitempty" validate:"chipset,omitempty"`
// ID of the chosen storage policy
// Required: false
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
} }
// GetRAM returns RAM field values // GetRAM returns RAM field values

@ -46,6 +46,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -12,11 +12,47 @@ import (
type AuditsRequest struct { type AuditsRequest struct {
// ID of the compute // ID of the compute
// Required: true // Required: true
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"` ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
// Find all audits after point in time
// Required: false
TimestampAT uint64 `url:"timestamp_at,omitempty" json:"timestamp_at,omitempty"`
// Find all audits before point in time
// Required: false
TimestampTO uint64 `url:"timestamp_to,omitempty" json:"timestamp_to,omitempty"`
// Find by user
// Required: false
User string `url:"user,omitempty" json:"user,omitempty"`
// Find by api endpoints
// Required: false
Call string `url:"call,omitempty" json:"call,omitempty"`
// Sort by one of supported fields, format ±<field>
// Required: false
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
// Page number
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
// Page size
// Required: false
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
// Find by HTTP min status code
// Required: false
MinStatusCode uint64 `url:"min_status_code,omitempty" json:"min_status_code,omitempty"`
// Find by HTTP max status code
// Required: false
MaxStatusCode uint64 `url:"max_status_code,omitempty" json:"max_status_code,omitempty"`
} }
// Audits gets audit records for the specified compute object // Audits gets audit records for the specified compute object
func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) { func (c Compute) Audits(ctx context.Context, req AuditsRequest) (*ListAudits, error) {
err := validators.ValidateRequest(req) err := validators.ValidateRequest(req)
if err != nil { if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err)) return nil, validators.ValidationErrors(validators.GetErrors(err))
@ -24,7 +60,7 @@ func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListAudits, err
url := "/cloudapi/compute/audits" url := "/cloudapi/compute/audits"
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -36,5 +72,5 @@ func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListAudits, err
return nil, err return nil, err
} }
return list, nil return &list, nil
} }

@ -0,0 +1,50 @@
package compute
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// ChangeSecGroupsRequest struct to change security groups for compute
type ChangeSecGroupsRequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
// Interface name or MAC address
// Required: true
Interface string `url:"interface" json:"interface" validate:"required"`
// List of security group IDs to assign to this interface
// Required: false
SecGroups []uint64 `url:"security_groups,omitempty" json:"security_groups,omitempty"`
// Flag indicating whether security groups are enabled for this interface
// Required: false
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
}
// ChangeSecGroups changes security groups for compute
func (c Compute) ChangeSecGroups(ctx context.Context, req ChangeSecGroupsRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/compute/change_security_groups"
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -27,6 +27,10 @@ type CreateTemplateFromBlankRequest struct {
// Required: true // Required: true
ImageType string `url:"imagetype" json:"imagetype" validate:"imageType"` ImageType string `url:"imagetype" json:"imagetype" validate:"imageType"`
// Storage policy id of disk. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Username for the image // Username for the image
// Required: false // Required: false
Username string `url:"username,omitempty" json:"username,omitempty"` Username string `url:"username,omitempty" json:"username,omitempty"`

@ -22,6 +22,10 @@ type DiskAddRequest struct {
// Required: true // Required: true
Size uint64 `url:"size" json:"size" validate:"required"` Size uint64 `url:"size" json:"size" validate:"required"`
// Storage policy id of disk. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Type of the disk // Type of the disk
// Should be one of: // Should be one of:
// - D // - D

@ -83,6 +83,7 @@ var computes = ListComputes{
VGPUs: []uint64{}, VGPUs: []uint64{},
VINSConnected: 0, VINSConnected: 0,
VirtualImageID: 0, VirtualImageID: 0,
ZoneID: 1,
}, },
{ {
ACL: ListACL{}, ACL: ListACL{},
@ -145,6 +146,7 @@ var computes = ListComputes{
VGPUs: []uint64{}, VGPUs: []uint64{},
VINSConnected: 0, VINSConnected: 0,
VirtualImageID: 0, VirtualImageID: 0,
ZoneID: 5,
}, },
}, },
EntryCount: 2, EntryCount: 2,

@ -58,6 +58,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -238,7 +238,13 @@ type ItemAudit struct {
} }
// List Detailed audits // List Detailed audits
type ListAudits []ItemAudit type ListAudits struct {
// Data
Data []ItemAudit `json:"data"`
// Entry count
EntryCount uint64 `json:"entryCount"`
}
// Short information about audit // Short information about audit
type ItemShortAudit struct { type ItemShortAudit struct {
@ -661,6 +667,9 @@ type ItemVNFInterface struct {
// Enabled // Enabled
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
// Enable security groups
EnableSecGroups bool `json:"enable_secgroups"`
// FLIPGroup ID // FLIPGroup ID
FLIPGroupID uint64 `json:"flipgroupId"` FLIPGroupID uint64 `json:"flipgroupId"`
@ -703,6 +712,9 @@ type ItemVNFInterface struct {
// QOS // QOS
QOS QOS `json:"qos"` QOS QOS `json:"qos"`
// List of security groups
SecGroups []uint64 `json:"security_groups"`
// SDN interface ID // SDN interface ID
SDNInterfaceID string `json:"sdn_interface_id"` SDNInterfaceID string `json:"sdn_interface_id"`
@ -848,17 +860,20 @@ type ItemComputeDisk struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy id of compute.
StoragePolicyID uint64 `json:"storage_policy_id"`
// Tech status // Tech status
TechStatus string `json:"techStatus"` TechStatus string `json:"techStatus"`
// Need to clean before destroy
ToClean bool `json:"to_clean"`
// Type // Type
Type string `json:"type"` Type string `json:"type"`
// Updated by // Updated by
UpdatedBy string `json:"updatedBy"` UpdatedBy string `json:"updatedBy"`
// Zone ID
ZoneID uint64 `json:"zoneId"`
} }
type ItemReplication struct { type ItemReplication struct {
@ -1161,6 +1176,9 @@ type ItemCompute struct {
// Virtual image ID // Virtual image ID
VirtualImageID uint64 `json:"virtualImageId"` VirtualImageID uint64 `json:"virtualImageId"`
// Zone ID
ZoneID uint64 `json:"zoneId"`
} }
// ListInfoDisks // ListInfoDisks

@ -42,12 +42,24 @@ type NetAttachRequest struct {
// Used only for EXTNET and DPDK // Used only for EXTNET and DPDK
// For DPDK must be 1-9216 // For DPDK must be 1-9216
// For EXTNET must be 1500-9216 // For EXTNET must be 1500-9216
// Required: false // Required: false
MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty" validate:"omitempty,mtu"` MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty" validate:"omitempty,mtu"`
// Unique identifier of logical port on SDN side // Unique identifier of logical port on SDN side
// Required: false // Required: false
SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty" validate:"omitempty"` SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty" validate:"omitempty"`
// List of security group IDs to assign to this interface
// Required: false
SecGroups []uint64 `url:"security_groups,omitempty" json:"security_groups,omitempty"`
// Flag indicating whether security groups are enabled for this interface
// Required: false
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
// Flag indicating whether this interface is enabled (only for VINS, EXTNET, DPDK, SDN, TRUNK)
// Required: false
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
} }
// NetAttach attaches network to compute and gets info about network // NetAttach attaches network to compute and gets info about network

@ -14,6 +14,10 @@ type RedeployRequest struct {
// Required: true // Required: true
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"` ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
// Storage policy id of compute. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// ID of the new OS image, if image change is required // ID of the new OS image, if image change is required
// Required: false // Required: false
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"` ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`

@ -0,0 +1,42 @@
package disks
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// ChangeDiskStoragePolicyRequest struct to change storage policy for disk
type ChangeDiskStoragePolicyRequest struct {
// ID of the disk
// Required: true
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
// ID of the storage policy to which to connect for disk
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
}
// ChangeDiskStoragePolicy changes storage policy for disk
func (d Disks) ChangeDiskStoragePolicy(ctx context.Context, req ChangeDiskStoragePolicyRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/disks/change_disk_storage_policy"
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -18,6 +18,10 @@ type CreateRequest struct {
// Required: true // Required: true
Name string `url:"name" json:"name" validate:"required"` Name string `url:"name" json:"name" validate:"required"`
// ID of the storage policy under the disk will be created
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Description of disk // Description of disk
// Required: false // Required: false
Description string `url:"description,omitempty" json:"description,omitempty"` Description string `url:"description,omitempty" json:"description,omitempty"`

@ -43,11 +43,6 @@ type FromPlatformDiskRequest struct {
// Required: false // Required: false
PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"` PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"`
// List of types of compute suitable for image
// Example: [ "KVM_X86" ]
// Required: true
Drivers []string `url:"drivers" json:"drivers" validate:"required"`
// Does this machine supports hot resize // Does this machine supports hot resize
// Required: false // Required: false
HotResize bool `url:"hotresize" json:"hotresize"` HotResize bool `url:"hotresize" json:"hotresize"`

@ -119,9 +119,15 @@ type ItemDisk struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy ID
StoragePolicyID uint64 `json:"storage_policy_id"`
// Tech status // Tech status
TechStatus string `json:"techStatus"` TechStatus string `json:"techStatus"`
// Need to clean before destroy
ToClean bool `json:"to_clean"`
// Type // Type
Type string `json:"type"` Type string `json:"type"`
@ -477,9 +483,15 @@ type RecordDisk struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy ID
StoragePolicyID uint64 `json:"storage_policy_id"`
// Tech status // Tech status
TechStatus string `json:"techStatus"` TechStatus string `json:"techStatus"`
// Need to clean before destroy
ToClean bool `json:"to_clean"`
// Type // Type
Type string `json:"type"` Type string `json:"type"`

@ -25,9 +25,13 @@ type ReplicateRequest struct {
// Pool name to create slave disk in // Pool name to create slave disk in
// Required: true // Required: true
PoolName string `url:"poolName" json:"poolName" validate:"required"` PoolName string `url:"poolName" json:"poolName" validate:"required"`
// ID of the storage policy under the disk will be created
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
} }
// Create an empty disk in chosen SEP and pool combination. // Replicate create an empty disk in chosen SEP and pool combination.
// Starts replication between chosen disk and newly created disk // Starts replication between chosen disk and newly created disk
// Note: only TATLIN type SEP are supported for replications between // Note: only TATLIN type SEP are supported for replications between
func (d Disks) Replicate(ctx context.Context, req ReplicateRequest) (uint64, error) { func (d Disks) Replicate(ctx context.Context, req ReplicateRequest) (uint64, error) {

@ -14,6 +14,9 @@ type RecordDPDKNet struct {
// Description // Description
Description string `json:"description"` Description string `json:"description"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Grid ID // Grid ID
GID uint64 `json:"gid"` GID uint64 `json:"gid"`
@ -63,6 +66,9 @@ type ItemDPDKNet struct {
// Description // Description
Description string `json:"description"` Description string `json:"description"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Grid ID // Grid ID
GID uint64 `json:"gid"` GID uint64 `json:"gid"`

@ -42,6 +42,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -172,6 +172,9 @@ type RecordExtNet struct {
// Excluded // Excluded
Excluded []Excluded `json:"excluded"` Excluded []Excluded `json:"excluded"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Free IPs // Free IPs
FreeIPs int64 `json:"free_ips"` FreeIPs int64 `json:"free_ips"`

@ -0,0 +1,41 @@
package image
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type ChangeStoragePolicyRequest struct {
// ID of the image to change the storage policy
// Required: true
ImageID uint64 `url:"image_id" json:"image_id" validate:"required"`
// ID of the storage policy to move the image to
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
}
// ChangeStoragePolicy changes the storage policy of the image chosen
func (i Image) ChangeStoragePolicy(ctx context.Context, req ChangeStoragePolicyRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/image/change_storage_policy"
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -35,6 +35,10 @@ type CreateRequest struct {
// Required: true // Required: true
AccountID uint64 `url:"accountId" json:"accountId" validate:"required"` AccountID uint64 `url:"accountId" json:"accountId" validate:"required"`
// ID of the chosen storage policy
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Select a network interface naming pattern for your Linux machine. eth - onboard, ens - pci slot naming // Select a network interface naming pattern for your Linux machine. eth - onboard, ens - pci slot naming
// Should be: // Should be:
// - eth // - eth
@ -69,11 +73,6 @@ type CreateRequest struct {
// Pool for image create // Pool for image create
// Required: false // Required: false
Pool string `url:"poolName,omitempty" json:"poolName,omitempty"` Pool string `url:"poolName,omitempty" json:"poolName,omitempty"`
// List of types of compute suitable for image
// Example: [ "KVM_X86" ]
// Required: true
Drivers []string `url:"drivers" json:"drivers" validate:"min=1,max=2,imageDrivers"`
} }
type asyncWrapperCreateRequest struct { type asyncWrapperCreateRequest struct {

@ -17,6 +17,11 @@ type CreateVirtualRequest struct {
// ID of real image to link this virtual image to upon creation // ID of real image to link this virtual image to upon creation
// Required: true // Required: true
TargetID uint64 `url:"targetId" json:"targetId" validate:"required"` TargetID uint64 `url:"targetId" json:"targetId" validate:"required"`
// AccountID to make the virtual image exclusive
// Required: false
// Default: 0
AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"`
} }
// CreateVirtual creates virtual image // CreateVirtual creates virtual image

@ -191,6 +191,9 @@ type RecordImage struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy ID
StoragePolicyID uint64 `json:"storage_policy_id"`
// Tech status // Tech status
TechStatus string `json:"techStatus"` TechStatus string `json:"techStatus"`

@ -22,14 +22,6 @@ type ListRequest struct {
// Required: false // Required: false
Status string `url:"status,omitempty" json:"status,omitempty"` Status string `url:"status,omitempty" json:"status,omitempty"`
// Find by worker driver
// Required: false
WorkerDriver string `url:"workerDriver,omitempty" json:"workerDriver,omitempty"`
// Find by master driver
// Required: false
MasterDriver string `url:"masterDriver,omitempty" json:"masterDriver,omitempty"`
// Find by network plugin // Find by network plugin
// Required: false // Required: false
NetworkPlugins string `url:"netPlugins,omitempty" json:"netPlugins,omitempty"` NetworkPlugins string `url:"netPlugins,omitempty" json:"netPlugins,omitempty"`

@ -18,14 +18,6 @@ type ListDeletedRequest struct {
// Required: false // Required: false
Name string `url:"name,omitempty" json:"name,omitempty"` Name string `url:"name,omitempty" json:"name,omitempty"`
// Find by worker driver
// Required: false
WorkerDriver string `url:"workerDriver,omitempty" json:"workerDriver,omitempty"`
// Find by master driver
// Required: false
MasterDriver string `url:"masterDriver,omitempty" json:"masterDriver,omitempty"`
// Find by network plugin // Find by network plugin
// Required: false // Required: false
NetworkPlugins string `url:"netPlugins,omitempty" json:"netPlugins,omitempty"` NetworkPlugins string `url:"netPlugins,omitempty" json:"netPlugins,omitempty"`

@ -31,6 +31,10 @@ type CreateRequest struct {
// Required: true // Required: true
NetworkPlugin string `url:"networkPlugin" json:"networkPlugin" validate:"required,networkPlugin"` NetworkPlugin string `url:"networkPlugin" json:"networkPlugin" validate:"required,networkPlugin"`
// ID of the chosen storage policy
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// ID of SEP to create boot disks for master nodes. Uses images SEP ID if not set // ID of SEP to create boot disks for master nodes. Uses images SEP ID if not set
// Required: false // Required: false
MasterSEPID uint64 `url:"masterSepId,omitempty" json:"masterSepId,omitempty"` MasterSEPID uint64 `url:"masterSepId,omitempty" json:"masterSepId,omitempty"`

@ -46,6 +46,11 @@ type ListRequest struct {
// Required: false // Required: false
IncludeDeleted bool `url:"includedeleted,omitempty" json:"includedeleted,omitempty"` IncludeDeleted bool `url:"includedeleted,omitempty" json:"includedeleted,omitempty"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Sort by one of supported fields, format +|-(field) // Sort by one of supported fields, format +|-(field)
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`

@ -17,6 +17,10 @@ type WorkersGroupAddRequest struct {
// Required: true // Required: true
Name string `url:"name" json:"name" validate:"required"` Name string `url:"name" json:"name" validate:"required"`
// ID of the chosen storage policy
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// ID of SEP to create boot disks for default worker nodes group. Uses images SEP ID if not set // ID of SEP to create boot disks for default worker nodes group. Uses images SEP ID if not set
// Required: false // Required: false
WorkerSEPID uint64 `url:"workerSepId,omitempty" json:"workerSepId,omitempty"` WorkerSEPID uint64 `url:"workerSepId,omitempty" json:"workerSepId,omitempty"`

@ -42,6 +42,18 @@ type Interface struct {
// SDN interface id // SDN interface id
// Required: false // Required: false
SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty"` SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty"`
// List of security group IDs to assign to this interface
// Required: false
SecGroups []uint64 `url:"security_groups,omitempty" json:"security_groups,omitempty"`
// Flag indicating whether security groups are enabled for this interface
// Required: false
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
// Flag indicating whether this interface is enabled (only for VINS, EXTNET, DPDK, SDN, TRUNK)
// Required: false
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
} }
// DataDisk detailed struct for DataDisks field in CreateRequest and CreateBlankRequest // DataDisk detailed struct for DataDisks field in CreateRequest and CreateBlankRequest
@ -54,6 +66,10 @@ type DataDisk struct {
// Required: true // Required: true
Size uint64 `url:"size" json:"size" validate:"required"` Size uint64 `url:"size" json:"size" validate:"required"`
// Storage policy id of disk. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Storage endpoint provider ID // Storage endpoint provider ID
// By default the same with boot disk // By default the same with boot disk
// Required: false // Required: false
@ -92,6 +108,10 @@ type CreateRequest struct {
// Required: true // Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"` RAM uint64 `url:"ram" json:"ram" validate:"required"`
// Storage policy id of сompute. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state // If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false // Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"` WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
@ -150,10 +170,6 @@ type CreateRequest struct {
// Required: false // Required: false
CustomFields string `url:"customFields,omitempty" json:"customFields,omitempty"` CustomFields string `url:"customFields,omitempty" json:"customFields,omitempty"`
// Type of compute Stateful (KVM_X86)
// Required: false
Driver string `url:"driver,omitempty" json:"driver,omitempty" validate:"omitempty,computeDriver"`
// Rule for VM placement with NUMA affinity. // Rule for VM placement with NUMA affinity.
// Possible values - none (placement without NUMA affinity), // Possible values - none (placement without NUMA affinity),
// strict (strictly with NUMA affinity, if not possible - do not start VM), // strict (strictly with NUMA affinity, if not possible - do not start VM),

@ -28,6 +28,10 @@ type CreateBlankRequest struct {
// Required: true // Required: true
RAM uint64 `url:"ram" json:"ram" validate:"required"` RAM uint64 `url:"ram" json:"ram" validate:"required"`
// Storage policy id of compute. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state // If True, the imageId, bootDisk, sepId, pool parameters are ignored and the compute is created without a boot disk in the stopped state
// Required: false // Required: false
WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"` WithoutBootDisk bool `url:"withoutBootDisk" json:"withoutBootDisk"`
@ -57,10 +61,6 @@ type CreateBlankRequest struct {
// Required: false // Required: false
Interfaces []Interface `url:"-" json:"interfaces,omitempty" validate:"omitempty,dive"` Interfaces []Interface `url:"-" json:"interfaces,omitempty" validate:"omitempty,dive"`
// Type of compute Stateful (KVM_X86)
// Required: false
Driver string `url:"driver,omitempty" json:"driver,omitempty" validate:"omitempty,computeDriver"`
// Type of the emulated system, Q35 or i440fx // Type of the emulated system, Q35 or i440fx
// Required: false // Required: false
Chipset string `url:"chipset,omitempty" json:"chipset,omitempty" validate:"omitempty,chipset"` Chipset string `url:"chipset,omitempty" json:"chipset,omitempty" validate:"omitempty,chipset"`

@ -50,6 +50,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -5,6 +5,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"
) )
@ -22,6 +23,10 @@ type CreateRequest struct {
// Required: true // Required: true
Name string `url:"name" json:"name" validate:"required,min=2"` Name string `url:"name" json:"name" validate:"required,min=2"`
// Storage policies
// Required: false
StoragePolicies []StoragePolicy `url:"storage_policies" json:"storage_policies"`
// Max size of memory in MB // Max size of memory in MB
// Required: false // Required: false
MaxMemoryCapacity int64 `url:"maxMemoryCapacity,omitempty" json:"maxMemoryCapacity,omitempty"` MaxMemoryCapacity int64 `url:"maxMemoryCapacity,omitempty" json:"maxMemoryCapacity,omitempty"`
@ -77,6 +82,11 @@ type CreateRequest struct {
SDNAccessGroupID string `url:"sdn_access_group_id,omitempty" json:"sdn_access_group_id,omitempty"` SDNAccessGroupID string `url:"sdn_access_group_id,omitempty" json:"sdn_access_group_id,omitempty"`
} }
type StoragePolicy struct {
ID int64 `url:"id" json:"id"`
Limit int `url:"limit" json:"limit"`
}
// Create creates resource group // Create creates resource group
func (r RG) Create(ctx context.Context, req CreateRequest) (uint64, error) { func (r RG) Create(ctx context.Context, req CreateRequest) (uint64, error) {
err := validators.ValidateRequest(req) err := validators.ValidateRequest(req)
@ -86,7 +96,7 @@ func (r RG) Create(ctx context.Context, req CreateRequest) (uint64, error) {
url := "/cloudapi/rg/create" url := "/cloudapi/rg/create"
res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := r.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil { if err != nil {
return 0, err return 0, err
} }

@ -134,6 +134,9 @@ type RecordResourceGroup struct {
// List of resource types // List of resource types
ResTypes []string `json:"resourceTypes"` ResTypes []string `json:"resourceTypes"`
// Storage policy ids
StoragePolicyIDs []uint64 `json:"storage_policy_ids"`
// SDN access group id // SDN access group id
SDNAccessGroupID string `json:"sdn_access_group_id"` SDNAccessGroupID string `json:"sdn_access_group_id"`
@ -233,6 +236,9 @@ type ItemResourceGroup struct {
// SDN access group id // SDN access group id
SDNAccessGroupID string `json:"sdn_access_group_id"` SDNAccessGroupID string `json:"sdn_access_group_id"`
// Storage policy ids
StoragePolicyIDs []uint64 `json:"storage_policy_ids"`
// Secret // Secret
Secret string `json:"secret"` Secret string `json:"secret"`
@ -308,6 +314,9 @@ type ResourceLimits struct {
// GPU units // GPU units
GPUUnits float64 `json:"gpu_units"` GPUUnits float64 `json:"gpu_units"`
// Storage policies
StoragePolicies []StoragePolicy `json:"storage_policy"`
} }
// Main information about affinity group // Main information about affinity group

@ -5,6 +5,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"
) )
@ -50,6 +51,10 @@ type UpdateRequest struct {
// Default: false // Default: false
// Required: false // Required: false
ClearUniqPools bool `url:"clearUniqPools" json:"clearUniqPools"` ClearUniqPools bool `url:"clearUniqPools" json:"clearUniqPools"`
// Storage policies
// Required: false
StoragePolicies []StoragePolicy `url:"-" json:"storage_policies,omitempty"`
} }
// Update updates resource group // Update updates resource group
@ -61,7 +66,7 @@ func (r RG) Update(ctx context.Context, req UpdateRequest) (bool, error) {
url := "/cloudapi/rg/update" url := "/cloudapi/rg/update"
res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := r.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil { if err != nil {
return false, err return false, err
} }

@ -0,0 +1,46 @@
package securitygroup
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type CreateRequest struct {
// Account ID that owns security group
// Required: true
AccountID uint64 `url:"account_id" json:"account_id" validate:"required"`
// Security group name
// Required: true
Name string `url:"name" json:"name" validate:"required"`
// Security group description
// Required: false
Description string `url:"description,omitempty" json:"description,omitempty"`
}
func (sg SecurityGroup) Create(ctx context.Context, req CreateRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
return 0, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/create"
res, err := sg.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil {
return 0, err
}
result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
}

@ -0,0 +1,63 @@
package securitygroup
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type CreateRuleRequest struct {
// Security group ID
// Required: true
SecurityGroupID uint64 `url:"security_group_id" json:"security_group_id" validate:"required"`
// Traffic direction (inbound/outbound)
// Required: true
Direction string `url:"direction" json:"direction" validate:"required,securityGroupDirection"`
// IP protocol version
// Default: IPv4
// Required: false
Ethertype string `url:"ethertype,omitempty" json:"ethertype,omitempty" validate:"omitempty,securityGroupEthertype"`
// Network protocol, available values : icmp, tcp, udp
// Required: false
Protocol string `url:"protocol,omitempty" json:"protocol,omitempty" validate:"omitempty,securityGroupProtocol"`
// Start port number (for TCP/UDP)
// Required: false
PortRangeMin uint64 `url:"port_range_min,omitempty" json:"port_range_min,omitempty"`
// End port number (for TCP/UDP)
// Required: false
PortRangeMax uint64 `url:"port_range_max,omitempty" json:"port_range_max,omitempty"`
// Remote IP prefix in CIDR notation
// Required: false
RemoteIPPrefix string `url:"remote_ip_prefix,omitempty" json:"remote_ip_prefix,omitempty"`
}
func (sg SecurityGroup) CreateRule(ctx context.Context, req CreateRuleRequest) (uint64, error) {
err := validators.ValidateRequest(req)
if err != nil {
return 0, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/create_rule"
res, err := sg.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil {
return 0, err
}
result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
}

@ -0,0 +1,36 @@
package securitygroup
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type DeleteRequest struct {
// Security group ID
// Required: true
SecurityGroupID uint64 `url:"security_group_id" json:"security_group_id" validate:"required"`
}
func (sg SecurityGroup) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/delete"
res, err := sg.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -0,0 +1,40 @@
package securitygroup
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type DeleteRuleRequest struct {
// Security group ID
// Required: true
SecurityGroupID uint64 `url:"security_group_id" json:"security_group_id" validate:"required"`
// Rule ID
// Required: true
RuleID uint64 `url:"rule_id" json:"rule_id" validate:"required"`
}
func (sg SecurityGroup) DeleteRule(ctx context.Context, req DeleteRuleRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/delete_rule"
res, err := sg.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -0,0 +1,80 @@
package securitygroup
// FilterByID returns ListSecurityGroups with specified ID.
func (lsg ListSecurityGroups) FilterByID(id uint64) ListSecurityGroups {
predicate := func(isg ItemSecurityGroup) bool {
return isg.ID == id
}
return lsg.FilterFunc(predicate)
}
// FilterByID returns ListSecurityGroups with specified Name.
func (lsg ListSecurityGroups) FilterByName(name string) ListSecurityGroups {
predicate := func(isg ItemSecurityGroup) bool {
return isg.Name == name
}
return lsg.FilterFunc(predicate)
}
// FilterByCreatedBy returns ListSecurityGroups with specified CreatedBy.
func (lsg ListSecurityGroups) FilterByCreatedBy(createdBy string) ListSecurityGroups {
predicate := func(isg ItemSecurityGroup) bool {
return isg.CreatedBy == createdBy
}
return lsg.FilterFunc(predicate)
}
// FilterByDescription returns ListSecurityGroups with specified Description.
func (lsg ListSecurityGroups) FilterByDescription(description string) ListSecurityGroups {
predicate := func(isg ItemSecurityGroup) bool {
return isg.Description == description
}
return lsg.FilterFunc(predicate)
}
// FilterByUpdatedBy returns ListSecurityGroups with specified UpdatedBy.
func (lsg ListSecurityGroups) FilterByUpdatedBy(updatedBy string) ListSecurityGroups {
predicate := func(isg ItemSecurityGroup) bool {
return isg.UpdatedBy == updatedBy
}
return lsg.FilterFunc(predicate)
}
// FilterByAccountID returns ListSecurityGroups with specified AccountID.
func (lsg ListSecurityGroups) FilterByAccountID(accountID uint64) ListSecurityGroups {
predicate := func(isg ItemSecurityGroup) bool {
return isg.AccountID == accountID
}
return lsg.FilterFunc(predicate)
}
// FilterFunc allows filtering ListSecurityGroups based on a user-specified predicate.
func (lsg ListSecurityGroups) FilterFunc(predicate func(ItemSecurityGroup) bool) ListSecurityGroups {
var result ListSecurityGroups
for _, item := range lsg.Data {
if predicate(item) {
result.Data = append(result.Data, item)
}
}
result.EntryCount = uint64(len(result.Data))
return result
}
// FindOne returns first found ItemSecurityGroup
// If none was found, returns an empty struct.
func (lsg ListSecurityGroups) FindOne() ItemSecurityGroup {
if len(lsg.Data) == 0 {
return ItemSecurityGroup{}
}
return lsg.Data[0]
}

@ -0,0 +1,87 @@
package securitygroup
import "testing"
var securityGroups = ListSecurityGroups{
Data: []ItemSecurityGroup{
{
ID: 1,
AccountID: 1,
Name: "sg1",
Description: "some desc",
CreatedBy: "user",
},
{
ID: 3,
AccountID: 3,
Name: "sg3",
Description: "some desc",
CreatedBy: "anotheruser",
},
{
ID: 5,
AccountID: 3,
Name: "sg5",
Description: "some other desc",
CreatedBy: "anotheruser",
UpdatedBy: "user",
},
},
EntryCount: 3,
}
func TestFilterByID(t *testing.T) {
actual := securityGroups.FilterByID(1).FindOne()
if actual.ID != 1 {
t.Fatal("expected ID 1, found: ", actual.ID)
}
}
func TestFilterByName(t *testing.T) {
actual := securityGroups.FilterByName("sg3").FindOne()
if actual.Name != "sg3" {
t.Fatal("expected Name sg3, found: ", actual.Name)
}
}
func TestFilterByDescription(t *testing.T) {
actual := securityGroups.FilterByDescription("some desc")
if len(actual.Data) != 2 {
t.Fatal("expected 2 found, actual: ", len(actual.Data))
}
for _, item := range actual.Data {
if item.Description != "some desc" {
t.Fatal("expected Description 'some desc', found: ", item.Description)
}
}
}
func TestFilterByAccountID(t *testing.T) {
actual := securityGroups.FilterByAccountID(1).FindOne()
if actual.AccountID != 1 {
t.Fatal("expected AccountID 1, found: ", actual.AccountID)
}
}
func TestFilterByCreatedBy(t *testing.T) {
actual := securityGroups.FilterByCreatedBy("anotheruser")
if len(actual.Data) != 2 {
t.Fatal("expected 2 found, actual: ", len(actual.Data))
}
for _, item := range actual.Data {
if item.CreatedBy != "anotheruser" {
t.Fatal("expected CreatedBy 'anotheruser', found: ", item.CreatedBy)
}
}
}
func TestFilterByUpdatedBy(t *testing.T) {
actual := securityGroups.FilterByUpdatedBy("user").FindOne()
if actual.UpdatedBy != "user" {
t.Fatal("expected UpdatedBy 'user', found: ", actual.UpdatedBy)
}
}

@ -0,0 +1,43 @@
package securitygroup
import (
"context"
"encoding/json"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type GetRequest struct {
// ID of security group
// Required: true
SecurityGroupID uint64 `url:"security_group_id" json:"security_group_id" validate:"required"`
}
func (sg SecurityGroup) Get(ctx context.Context, req GetRequest) (*RecordSecurityGroup, error) {
res, err := sg.GetRaw(ctx, req)
if err != nil {
return nil, err
}
info := RecordSecurityGroup{}
err = json.Unmarshal(res, &info)
if err != nil {
return nil, err
}
return &info, nil
}
func (sg SecurityGroup) GetRaw(ctx context.Context, req GetRequest) ([]byte, error) {
err := validators.ValidateRequest(req)
if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/get"
res, err := sg.client.DecortApiCall(ctx, http.MethodGet, url, req)
return res, err
}

@ -0,0 +1,86 @@
package securitygroup
import (
"context"
"encoding/json"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type ListRequest struct {
// Search by security group id
// Required: false
ByID uint64 `url:"by_id,omitempty" json:"by_id,omitempty"`
// Search by account id
// Required: false
AccountID uint64 `url:"account_id,omitempty" json:"account_id,omitempty"`
// Search by security group name
// Required: false
Name string `url:"name,omitempty" json:"name,omitempty"`
// Search by security group description
// Required: false
Description string `url:"description,omitempty" json:"description,omitempty"`
// Search by created after time (unix timestamp)
// Required: false
CreatedMin uint64 `url:"created_min,omitempty" json:"created_min,omitempty"`
// Search by created before time (unix timestamp)
// Required: false
CreatedMax uint64 `url:"created_max,omitempty" json:"created_max,omitempty"`
// Search by updated after time (unix timestamp)
// Required: false
UpdatedMin uint64 `url:"updated_min,omitempty" json:"updated_min,omitempty"`
// Search by updated before time (unix timestamp)
// Required: false
UpdatedMax uint64 `url:"updated_max,omitempty" json:"updated_max,omitempty"`
// Sort by one of supported fields, format ±<field>
// Required: false
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
// Page number
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
// Page size
// Required: false
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
}
// List gets list of security groups as a ListSecurityGroups struct
func (sg SecurityGroup) List(ctx context.Context, req ListRequest) (*ListSecurityGroups, error) {
res, err := sg.ListRaw(ctx, req)
if err != nil {
return nil, err
}
list := ListSecurityGroups{}
err = json.Unmarshal(res, &list)
if err != nil {
return nil, err
}
return &list, nil
}
// ListRaw gets list of security groups as an array of bytes
func (sg SecurityGroup) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
if err := validators.ValidateRequest(req); err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/list"
res, err := sg.client.DecortApiCall(ctx, http.MethodGet, url, req)
return res, err
}

@ -0,0 +1,43 @@
package securitygroup
type ListSecurityGroups struct {
Data []ItemSecurityGroup `json:"data"`
EntryCount uint64 `json:"entryCount"`
}
type ItemSecurityGroup struct {
ID uint64 `json:"id"`
AccountID uint64 `json:"account_id"`
Name string `json:"name"`
Description string `json:"description"`
Rules Rules `json:"rules"`
CreatedAt uint64 `json:"created_at"`
UpdatedAt uint64 `json:"updated_at"`
CreatedBy string `json:"created_by"`
UpdatedBy string `json:"updated_by"`
}
type RecordSecurityGroup struct {
ID uint64 `json:"id"`
AccountID uint64 `json:"account_id"`
Name string `json:"name"`
Description string `json:"description"`
Rules Rules `json:"rules"`
CreatedAt uint64 `json:"created_at"`
UpdatedAt uint64 `json:"updated_at"`
CreatedBy string `json:"created_by"`
UpdatedBy string `json:"updated_by"`
}
type Rules []Rule
type Rule struct {
ID uint64 `json:"id"`
Direction string `json:"direction"`
Ethertype string `json:"ethertype"`
Protocol string `json:"protocol"`
PortRangeMin uint64 `json:"port_range_min"`
PortRangeMax uint64 `json:"port_range_max"`
RemoteIPPrefix string `json:"remote_ip_prefix"`
RemoteGroupID uint64 `json:"remote_group_id"`
}

@ -0,0 +1,15 @@
package securitygroup
import "repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
// Structure for creating request to storage policy
type SecurityGroup struct {
client interfaces.Caller
}
// Builder for stack endpoint
func New(client interfaces.Caller) *SecurityGroup {
return &SecurityGroup{
client: client,
}
}

@ -0,0 +1,41 @@
package securitygroup
import "sort"
// SortByCreatedAt sorts ListSecurityGroups by the CreatedAt field in ascending order.
//
// If inverse param is set to true, the order is reversed.
func (lsg ListSecurityGroups) SortByCreatedAt(inverse bool) ListSecurityGroups {
if len(lsg.Data) < 2 {
return lsg
}
sort.Slice(lsg.Data, func(i, j int) bool {
if inverse {
return lsg.Data[i].CreatedAt > lsg.Data[j].CreatedAt
}
return lsg.Data[i].CreatedAt < lsg.Data[j].CreatedAt
})
return lsg
}
// SortByUpdatedAt sorts ListSecurityGroups by the UpdatedAt field in ascending order.
//
// If inverse param is set to true, the order is reversed.
func (lsg ListSecurityGroups) SortByUpdatedAt(inverse bool) ListSecurityGroups {
if len(lsg.Data) < 2 {
return lsg
}
sort.Slice(lsg.Data, func(i, j int) bool {
if inverse {
return lsg.Data[i].UpdatedAt > lsg.Data[j].UpdatedAt
}
return lsg.Data[i].UpdatedAt < lsg.Data[j].UpdatedAt
})
return lsg
}

@ -0,0 +1,51 @@
package securitygroup
import (
"context"
"encoding/json"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type UpdateRequest struct {
// Security group ID
// Required: true
SecurityGroupID uint64 `url:"security_group_id" json:"security_group_id" validate:"required"`
// New security group name
// Required: false
Name string `url:"name,omitempty" json:"name,omitempty"`
// New security group description
// Required: false
Description string `url:"description,omitempty" json:"description,omitempty"`
}
func (sg SecurityGroup) Update(ctx context.Context, req UpdateRequest) (*RecordSecurityGroup, error) {
res, err := sg.UpdateRaw(ctx, req)
if err != nil {
return nil, err
}
info := RecordSecurityGroup{}
err = json.Unmarshal(res, &info)
if err != nil {
return nil, err
}
return &info, nil
}
func (sg SecurityGroup) UpdateRaw(ctx context.Context, req UpdateRequest) ([]byte, error) {
err := validators.ValidateRequest(req)
if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/security_group/update"
res, err := sg.client.DecortApiCall(ctx, http.MethodPost, url, req)
return res, err
}

@ -0,0 +1,10 @@
package cloudapi
import (
securitygroup "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/security_group"
)
// Accessing the Security Group method group
func (ca *CloudAPI) SecurityGroup() *securitygroup.SecurityGroup {
return securitygroup.New(ca.client)
}

@ -0,0 +1,43 @@
package storagepolicy
import (
"context"
"encoding/json"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type GetRequest struct {
// ID of storage policy
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
}
func (sp StoragePolicy) Get(ctx context.Context, req GetRequest) (*InfoStoragePolicy, error) {
res, err := sp.GetRaw(ctx, req)
if err != nil {
return nil, err
}
info := InfoStoragePolicy{}
err = json.Unmarshal(res, &info)
if err != nil {
return nil, err
}
return &info, nil
}
func (sp StoragePolicy) GetRaw(ctx context.Context, req GetRequest) ([]byte, error) {
err := validators.ValidateRequest(req)
if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/storage_policy/get"
res, err := sp.client.DecortApiCall(ctx, http.MethodGet, url, req)
return res, err
}

@ -0,0 +1,90 @@
package storagepolicy
import (
"context"
"encoding/json"
"net/http"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type ListRequest struct {
// ID of account ID
// Required: true
AccountID uint64 `url:"account_id" json:"account_id" validate:"required"`
// Page number
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
// Page size
// Required: false
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
// Search by storage policy ID
// Required: false
ByID uint64 `url:"by_id,omitempty" json:"by_id,omitempty"`
// Search by storage policy name
// Required: false
Name string `url:"name,omitempty" json:"name,omitempty"`
// Search by storage policy status
// Required: false
Status string `url:"status,omitempty" json:"status,omitempty"`
// Search by storage policy desc
// Required: false
Desc string `url:"desc,omitempty" json:"desc,omitempty"`
// Search by storage policy iops limit
// Required: false
LimitIOPS uint64 `url:"limit_iops,omitempty" json:"limit_iops,omitempty"`
// Sort by one of supported fields, format ±<field>
// Required: false
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
// Search by resgroup id
// Required: false
ResgroupID uint64 `url:"resgroup_id,omitempty" json:"resgroup_id,omitempty"`
// Search by sep id
// Required: false
SepID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
// Search by pool name
// Required: false
PoolName string `url:"pool_name,omitempty" json:"pool_name,omitempty"`
}
// List gets list of storage policies as a ListStoragePolicies struct
func (sp StoragePolicy) List(ctx context.Context, req ListRequest) (*ListStoragePolicies, error) {
res, err := sp.ListRaw(ctx, req)
if err != nil {
return nil, err
}
list := ListStoragePolicies{}
err = json.Unmarshal(res, &list)
if err != nil {
return nil, err
}
return &list, nil
}
// ListRaw gets list of storage policies as an array of bytes
func (sp StoragePolicy) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
if err := validators.ValidateRequest(req); err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudapi/storage_policy/list"
res, err := sp.client.DecortApiCall(ctx, http.MethodGet, url, req)
return res, err
}

@ -0,0 +1,40 @@
package storagepolicy
type ListStoragePolicies struct {
Data []ItemStoragePolicy `json:"data"`
EntryCount uint64 `json:"entryCount"`
}
type ItemStoragePolicy struct {
ID uint64 `json:"id"`
GUID uint64 `json:"guid"`
Name string `json:"name"`
Description string `json:"description"`
AccessSepPools ListAccessSepPools `json:"access_seps_pools"`
Status string `json:"status"`
LimitIOPS uint64 `json:"limit_iops"`
Usage Usage `json:"usage"`
}
type InfoStoragePolicy struct {
ID uint64 `json:"id"`
GUID uint64 `json:"guid"`
Name string `json:"name"`
Description string `json:"description"`
AccessSepPools ListAccessSepPools `json:"access_seps_pools"`
Status string `json:"status"`
LimitIOPS uint64 `json:"limit_iops"`
Usage Usage `json:"usage"`
}
type ListAccessSepPools []AccessSepPool
type AccessSepPool struct {
SepID uint64 `json:"sep_id"`
PoolNames []string `json:"pool_names"`
}
type Usage struct {
Accounts []uint64 `json:"accounts"`
Resgroups []uint64 `json:"resgroups"`
}

@ -0,0 +1,15 @@
package storagepolicy
import "repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
// Structure for creating request to storage policy
type StoragePolicy struct {
client interfaces.Caller
}
// Builder for stack endpoint
func New(client interfaces.Caller) *StoragePolicy {
return &StoragePolicy{
client: client,
}
}

@ -0,0 +1,10 @@
package cloudapi
import (
storagepolicy "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/storage_policy"
)
// Accessing the Storage Policy method group
func (ca *CloudAPI) StoragePolicy() *storagepolicy.StoragePolicy {
return storagepolicy.New(ca.client)
}

@ -27,6 +27,9 @@ type ListRequest struct {
// Page size // Page size
Size uint64 `url:"size,omitempty" json:"size,omitempty"` Size uint64 `url:"size,omitempty" json:"size,omitempty"`
// Status
Status string `url:"status,omitempty" json:"status,omitempty"`
} }
// List gets list of all trunks as a ListTrunks struct // List gets list of all trunks as a ListTrunks struct

@ -46,6 +46,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -673,6 +673,9 @@ type RecordVINS struct {
// Description // Description
Description string `json:"desc"` Description string `json:"desc"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Grid ID // Grid ID
GID uint64 `json:"gid"` GID uint64 `json:"gid"`

@ -22,12 +22,30 @@ type RecordZone struct {
// Name // Name
Name string `json:"name"` Name string `json:"name"`
// List of associated account IDs
AccountIDs []uint64 `json:"accountIds"`
// List of associated bservice IDs
BserviceIDs []uint64 `json:"bserviceIds"`
// List of associated compute IDs
ComputeIDs []uint64 `json:"computeIds"`
// Description // Description
Description string `json:"description"` Description string `json:"description"`
// Deletable flag // Deletable flag
Deletable bool `json:"deletable"` Deletable bool `json:"deletable"`
// List of associated ExtNet IDs
ExtnetIDs []uint64 `json:"extnetIds"`
// List of associated K8s IDs
K8SIDs []uint64 `json:"k8sIds"`
// List of associated LB IDs
LBIDs []uint64 `json:"lbIds"`
// Status // Status
Status string `json:"status"` Status string `json:"status"`
@ -39,4 +57,7 @@ type RecordZone struct {
// List of associated Node IDs // List of associated Node IDs
NodeIDs []uint64 `json:"nodeIds"` NodeIDs []uint64 `json:"nodeIds"`
// List of associated VINS IDs
VinsIDs []uint64 `json:"vinsIds"`
} }

@ -0,0 +1,46 @@
package account
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// AddStoragePolicyRequest struct for adding storage policy to the account
type AddStoragePolicyRequest struct {
// ID of account to add to
// Required: true
AccountID uint64 `url:"account_id" json:"account_id" validate:"required"`
// ID of the storage policy to which to connect account
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Limit storage resources GB. Or -1 unlimit
// Required: false
Limit int `url:"limit,omitempty" json:"limit,omitempty"`
}
// AddStoragePolicy add storage policy to the account.
func (a Account) AddStoragePolicy(ctx context.Context, req AddStoragePolicyRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/account/add_storage_policy"
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -5,6 +5,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"
) )
@ -26,6 +27,10 @@ type CreateRequest struct {
// Required: false // Required: false
EmailAddress string `url:"emailaddress,omitempty" json:"emailaddress,omitempty" validate:"omitempty,email"` EmailAddress string `url:"emailaddress,omitempty" json:"emailaddress,omitempty" validate:"omitempty,email"`
// Storage policies
// Required: false
StoragePolicies []StoragePolicy `url:"-" json:"storage_policies" validate:"required"`
// Max size of memory in MB // Max size of memory in MB
// Required: false // Required: false
MaxMemoryCapacity int64 `url:"maxMemoryCapacity,omitempty" json:"maxMemoryCapacity,omitempty"` MaxMemoryCapacity int64 `url:"maxMemoryCapacity,omitempty" json:"maxMemoryCapacity,omitempty"`
@ -73,6 +78,11 @@ type CreateRequest struct {
ZoneIDs []uint64 `url:"zoneIds,omitempty" json:"zoneIds,omitempty"` ZoneIDs []uint64 `url:"zoneIds,omitempty" json:"zoneIds,omitempty"`
} }
type StoragePolicy struct {
ID int64 `url:"id" json:"id"`
Limit int `url:"limit" json:"limit"`
}
// Create creates account // Create creates account
// Setting a cloud unit maximum to -1 or empty will not put any restrictions on the resource // Setting a cloud unit maximum to -1 or empty will not put any restrictions on the resource
func (a Account) Create(ctx context.Context, req CreateRequest) (uint64, error) { func (a Account) Create(ctx context.Context, req CreateRequest) (uint64, error) {
@ -83,7 +93,7 @@ func (a Account) Create(ctx context.Context, req CreateRequest) (uint64, error)
url := "/cloudbroker/account/create" url := "/cloudbroker/account/create"
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := a.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil { if err != nil {
return 0, err return 0, err
} }

@ -0,0 +1,42 @@
package account
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// DelStoragePolicyRequest struct for deleting storage policy to the account
type DelStoragePolicyRequest struct {
// ID of account
// Required: true
AccountID uint64 `url:"account_id" json:"account_id" validate:"required"`
// ID of the storage policy to which to disconnect account
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
}
// DelStoragePolicy delete storage policy to the account.
func (a Account) DelStoragePolicy(ctx context.Context, req DelStoragePolicyRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/account/del_storage_policy"
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -30,6 +30,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -133,6 +133,9 @@ type ResourceLimits struct {
// GPUUnits // GPUUnits
GPUUnits float64 `json:"gpu_units"` GPUUnits float64 `json:"gpu_units"`
// Storage policies
StoragePolicies []StoragePolicy `json:"storage_policy"`
} }
// Main information about account // Main information about account
@ -200,6 +203,9 @@ type InfoAccount struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy ids
StoragePolicyIDs []uint64 `json:"storage_policy_ids"`
// UniqPools // UniqPools
UniqPools []string `json:"uniqPools"` UniqPools []string `json:"uniqPools"`
@ -234,7 +240,7 @@ type RecordAccount struct {
ACL []ACLWithEmails `json:"acl"` ACL []ACLWithEmails `json:"acl"`
// Zones IDs // Zones IDs
ZoneIDs []ZoneID ZoneIDs []ZoneID `json:"zoneIds"`
} }
// More information about account // More information about account
@ -249,7 +255,7 @@ type ItemAccount struct {
InfoAccount InfoAccount
// Zones // Zones
ZoneIDs []uint64 ZoneIDs []uint64 `json:"zoneIds"`
} }
// List of accounts // List of accounts

@ -5,6 +5,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"
) )
@ -46,6 +47,10 @@ type UpdateRequest struct {
// Required: false // Required: false
SendAccessEmails bool `url:"sendAccessEmails" json:"sendAccessEmails"` SendAccessEmails bool `url:"sendAccessEmails" json:"sendAccessEmails"`
// Storage policies
// Required: false
StoragePolicies []StoragePolicy `url:"-" json:"storage_policies,omitempty"`
// Limit (positive) or disable (0) GPU resources // Limit (positive) or disable (0) GPU resources
// Required: false // Required: false
GPUUnits int64 `url:"gpu_units,omitempty" json:"gpu_units,omitempty"` GPUUnits int64 `url:"gpu_units,omitempty" json:"gpu_units,omitempty"`
@ -74,7 +79,7 @@ func (a Account) Update(ctx context.Context, req UpdateRequest) (bool, error) {
url := "/cloudbroker/account/update" url := "/cloudbroker/account/update"
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := a.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
if err != nil { if err != nil {
return false, err return false, err
} }

@ -11,6 +11,9 @@ type ItemAudit struct {
// GUID // GUID
GUID string `json:"guid"` GUID string `json:"guid"`
// Correlation ID
CorrelationID string `json:"correlation_id"`
// Kwargs // Kwargs
Kwargs string `json:"kwargs"` Kwargs string `json:"kwargs"`
@ -60,6 +63,9 @@ type RecordAudit struct {
// Call // Call
Call string `json:"call"` Call string `json:"call"`
// Correlation ID
CorrelationID string `json:"correlation_id"`
// GUID // GUID
GUID string `json:"guid"` GUID string `json:"guid"`

@ -38,11 +38,9 @@ type GroupAddRequest struct {
// Required: true // Required: true
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"` ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
// Compute driver // Compute driver like a KVM_X86, etc.
// should be one of:
// - KVM_X86
// Required: true // Required: true
Driver string `url:"driver" json:"driver" validate:"driver"` Driver string `url:"driver" json:"driver" validate:"required"`
// Storage endpoint provider ID // Storage endpoint provider ID
// Required: false // Required: false
@ -75,6 +73,10 @@ type GroupAddRequest struct {
//Chipset "i440fx" or "Q35 //Chipset "i440fx" or "Q35
//Required: false //Required: false
Chipset string `url:"chipset,omitempty" json:"chipset,omitempty" validate:"chipset"` Chipset string `url:"chipset,omitempty" json:"chipset,omitempty" validate:"chipset"`
// ID of the chosen storage policy
// Required: false
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
} }
// GetRAM returns RAM field values // GetRAM returns RAM field values

@ -42,6 +42,11 @@ type ListRequest struct {
// Required: false // Required: false
AccountName string `url:"accountName,omitempty" json:"accountName,omitempty"` AccountName string `url:"accountName,omitempty" json:"accountName,omitempty"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Sort by one of supported fields, format +|-(field) // Sort by one of supported fields, format +|-(field)
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`

@ -12,11 +12,47 @@ import (
type AuditsRequest struct { type AuditsRequest struct {
// ID of the compute // ID of the compute
// Required: true // Required: true
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"` ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
// Find all audits after point in time
// Required: false
TimestampAT uint64 `url:"timestamp_at,omitempty" json:"timestamp_at,omitempty"`
// Find all audits before point in time
// Required: false
TimestampTO uint64 `url:"timestamp_to,omitempty" json:"timestamp_to,omitempty"`
// Find by user
// Required: false
User string `url:"user,omitempty" json:"user,omitempty"`
// Find by api endpoints
// Required: false
Call string `url:"call,omitempty" json:"call,omitempty"`
// Sort by one of supported fields, format ±<field>
// Required: false
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
// Page number
// Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
// Page size
// Required: false
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
// Find by HTTP min status code
// Required: false
MinStatusCode uint64 `url:"min_status_code,omitempty" json:"min_status_code,omitempty"`
// Find by HTTP max status code
// Required: false
MaxStatusCode uint64 `url:"max_status_code,omitempty" json:"max_status_code,omitempty"`
} }
// Audits gets audit records for the specified compute object // Audits gets audit records for the specified compute object
func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListDetailedAudits, error) { func (c Compute) Audits(ctx context.Context, req AuditsRequest) (*ListDetailedAudits, error) {
err := validators.ValidateRequest(req) err := validators.ValidateRequest(req)
if err != nil { if err != nil {
return nil, validators.ValidationErrors(validators.GetErrors(err)) return nil, validators.ValidationErrors(validators.GetErrors(err))
@ -24,7 +60,7 @@ func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListDetailedAud
url := "/cloudbroker/compute/audits" url := "/cloudbroker/compute/audits"
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -36,5 +72,5 @@ func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListDetailedAud
return nil, err return nil, err
} }
return list, nil return &list, nil
} }

@ -0,0 +1,50 @@
package compute
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// ChangeSecGroupsRequest struct to change security groups for compute
type ChangeSecGroupsRequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
// Interface name or MAC address
// Required: true
Interface string `url:"interface" json:"interface" validate:"required"`
// List of security group IDs to assign to this interface
// Required: false
SecGroups []uint64 `url:"security_groups,omitempty" json:"security_groups,omitempty"`
// Flag indicating whether security groups are enabled for this interface
// Required: false
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
}
// ChangeSecGroups changes security groups for compute
func (c Compute) ChangeSecGroups(ctx context.Context, req ChangeSecGroupsRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/compute/change_security_groups"
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -27,6 +27,10 @@ type CreateTemplateFromBlankRequest struct {
// Required: true // Required: true
ImageType string `url:"imagetype" json:"imagetype" validate:"imageType"` ImageType string `url:"imagetype" json:"imagetype" validate:"imageType"`
// Storage policy id of compute. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Username for the image // Username for the image
// Required: false // Required: false
Username string `url:"username,omitempty" json:"username,omitempty"` Username string `url:"username,omitempty" json:"username,omitempty"`

@ -27,6 +27,10 @@ type DiskAddRequest struct {
// Required: false // Required: false
SepID uint64 `url:"sepId,omitempty" json:"sepId,omitempty"` SepID uint64 `url:"sepId,omitempty" json:"sepId,omitempty"`
// Storage policy id of compute. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Type of the disk // Type of the disk
// Should be one of: // Should be one of:
// - D // - D

@ -74,6 +74,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -25,7 +25,7 @@ type MigrateRequest struct {
Force bool `url:"force,omitempty" json:"force,omitempty"` Force bool `url:"force,omitempty" json:"force,omitempty"`
} }
type asyncWrapperMigrateRequest struct { type AsyncWrapperMigrateRequest struct {
MigrateRequest MigrateRequest
SyncMode bool `url:"sync"` SyncMode bool `url:"sync"`
} }
@ -39,7 +39,7 @@ func (c Compute) Migrate(ctx context.Context, req MigrateRequest) (bool, error)
url := "/cloudbroker/compute/migrate" url := "/cloudbroker/compute/migrate"
syncReq := asyncWrapperMigrateRequest{MigrateRequest: req, SyncMode: true} syncReq := AsyncWrapperMigrateRequest{MigrateRequest: req, SyncMode: true}
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, syncReq) res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, syncReq)
if err != nil { if err != nil {
@ -63,7 +63,7 @@ func (c Compute) AsyncMigrate(ctx context.Context, req MigrateRequest) (string,
url := "/cloudbroker/compute/migrate" url := "/cloudbroker/compute/migrate"
asyncReq := asyncWrapperMigrateRequest{MigrateRequest: req, SyncMode: false} asyncReq := AsyncWrapperMigrateRequest{MigrateRequest: req, SyncMode: false}
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, asyncReq) res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, asyncReq)
if err != nil { if err != nil {

@ -221,8 +221,14 @@ type ItemDetailedAudit struct {
User string `json:"user"` User string `json:"user"`
} }
// List of detailed audit // List Detailed audits
type ListDetailedAudits []ItemDetailedAudit type ListDetailedAudits struct {
// Data
Data []ItemDetailedAudit `json:"data"`
// Entry count
EntryCount uint64 `json:"entryCount"`
}
// Main information about port forward // Main information about port forward
type ItemPFW struct { type ItemPFW struct {
@ -475,9 +481,15 @@ type ItemDisk struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy id of disk.
StoragePolicyID uint64 `json:"storage_policy_id"`
// Tech status // Tech status
TechStatus string `json:"techStatus"` TechStatus string `json:"techStatus"`
// Need to clean before destroy
ToClean bool `json:"to_clean"`
// Type // Type
Type string `json:"type"` Type string `json:"type"`
@ -525,6 +537,9 @@ type ItemInterface struct {
// Enabled // Enabled
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
// Enable security groups
EnableSecGroups bool `json:"enable_secgroups"`
// FLIPGroup ID // FLIPGroup ID
FLIPGroupID uint64 `json:"flipgroupId"` FLIPGroupID uint64 `json:"flipgroupId"`
@ -567,6 +582,9 @@ type ItemInterface struct {
// QOS // QOS
QOS QOS `json:"qos"` QOS QOS `json:"qos"`
// List of security groups
SecGroups []uint64 `json:"security_groups"`
// SDN interface ID // SDN interface ID
SDNInterfaceID string `json:"sdn_interface_id"` SDNInterfaceID string `json:"sdn_interface_id"`

@ -42,12 +42,24 @@ type NetAttachRequest struct {
// Used only for EXTNET and DPDK // Used only for EXTNET and DPDK
// For DPDK must be 1-9216 // For DPDK must be 1-9216
// For EXTNET must be 1500-9216 // For EXTNET must be 1500-9216
// Required: false // Required: false
MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty" validate:"omitempty,mtu"` MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty" validate:"omitempty,mtu"`
// Unique identifier of logical port on SDN side // Unique identifier of logical port on SDN side
// Required: false // Required: false
SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty" validate:"omitempty"` SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty" validate:"omitempty"`
// List of security group IDs to assign to this interface
// Required: false
SecGroups []uint64 `url:"security_groups,omitempty" json:"security_groups,omitempty"`
// Flag indicating whether security groups are enabled for this interface
// Required: false
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
// Flag indicating whether this interface is enabled (only for VINS, EXTNET, DPDK, SDN, TRUNK)
// Required: false
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
} }
// NetAttach attaches network to compute and gets info about network // NetAttach attaches network to compute and gets info about network

@ -18,6 +18,10 @@ type RedeployRequest struct {
// Required: false // Required: false
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"` ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
// Storage policy id of compute. The rules of the specified storage policy will be used.
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// New size for the boot disk in GB, if boot disk size change is required // New size for the boot disk in GB, if boot disk size change is required
// Required: false // Required: false
DiskSize uint64 `url:"diskSize,omitempty" json:"diskSize,omitempty"` DiskSize uint64 `url:"diskSize,omitempty" json:"diskSize,omitempty"`

@ -0,0 +1,42 @@
package disks
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
// ChangeDiskStoragePolicyRequest struct to change storage policy for disk
type ChangeDiskStoragePolicyRequest struct {
// ID of the disk
// Required: true
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
// ID of the storage policy to which to connect account
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
}
// ChangeDiskStoragePolicy changes storage policy for disk
func (d Disks) ChangeDiskStoragePolicy(ctx context.Context, req ChangeDiskStoragePolicyRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/disks/change_disk_storage_policy"
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -18,6 +18,10 @@ type CreateRequest struct {
// Required: true // Required: true
Name string `url:"name" json:"name" validate:"required"` Name string `url:"name" json:"name" validate:"required"`
// ID of the storage policy under the disk will be created
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Description of disk // Description of disk
// Required: false // Required: false
Description string `url:"description,omitempty" json:"description,omitempty"` Description string `url:"description,omitempty" json:"description,omitempty"`

@ -43,11 +43,6 @@ type FromPlatformDiskRequest struct {
// Required: false // Required: false
PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"` PoolName string `url:"poolName,omitempty" json:"poolName,omitempty"`
// List of types of compute suitable for image
// Example: [ "KVM_X86" ]
// Required: true
Drivers []string `url:"drivers" json:"drivers" validate:"required"`
// Does this machine supports hot resize // Does this machine supports hot resize
// Required: false // Required: false
HotResize bool `url:"hotresize" json:"hotresize"` HotResize bool `url:"hotresize" json:"hotresize"`

@ -170,9 +170,15 @@ type InfoDisk struct {
// Status // Status
Status string `json:"status"` Status string `json:"status"`
// Storage policy ID
StoragePolicyID uint64 `json:"storage_policy_id"`
// Tech status // Tech status
TechStatus string `json:"techStatus"` TechStatus string `json:"techStatus"`
// Need to clean before destroy
ToClean bool `json:"to_clean"`
// Type // Type
Type string `json:"type"` Type string `json:"type"`

@ -25,9 +25,13 @@ type ReplicateRequest struct {
// Pool name to create slave disk in // Pool name to create slave disk in
// Required: true // Required: true
PoolName string `url:"poolName" json:"poolName" validate:"required"` PoolName string `url:"poolName" json:"poolName" validate:"required"`
// ID of the storage policy under the disk will be created
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
} }
// Create an empty disk in chosen SEP and pool combination. // Replicate create an empty disk in chosen SEP and pool combination.
// Starts replication between chosen disk and newly created disk // Starts replication between chosen disk and newly created disk
// Note: only TATLIN type SEP are supported for replications between // Note: only TATLIN type SEP are supported for replications between
func (d Disks) Replicate(ctx context.Context, req ReplicateRequest) (uint64, error) { func (d Disks) Replicate(ctx context.Context, req ReplicateRequest) (uint64, error) {

@ -14,6 +14,9 @@ type RecordDPDKNet struct {
// Description // Description
Description string `json:"description"` Description string `json:"description"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Grid ID // Grid ID
GID uint64 `json:"gid"` GID uint64 `json:"gid"`
@ -63,6 +66,9 @@ type ItemDPDKNet struct {
// Description // Description
Description string `json:"description"` Description string `json:"description"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Grid ID // Grid ID
GID uint64 `json:"gid"` GID uint64 `json:"gid"`

@ -37,6 +37,10 @@ type UpdateRequest struct {
// Name of OVS Bridge to use for DPDK network // Name of OVS Bridge to use for DPDK network
// Required: true // Required: true
OVSBridge string `url:"ovsBridge,omitempty" json:"ovsBridge,omitempty"` OVSBridge string `url:"ovsBridge,omitempty" json:"ovsBridge,omitempty"`
// Flag indicating whether security groups are enabled for this network
// Required: false
EnableSecGroups interface{} `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty" validate:"omitempty,isBool"`
} }
// Update updates a DPDK networks // Update updates a DPDK networks

@ -42,6 +42,11 @@ type ListRequest struct {
// Required: false // Required: false
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"` SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
// Sort by zone id
// Default value: 0
// Required: false
ZoneID uint64 `url:"zone_id,omitempty" json:"zone_id,omitempty"`
// Page number // Page number
// Required: false // Required: false
Page uint64 `url:"page,omitempty" json:"page,omitempty"` Page uint64 `url:"page,omitempty" json:"page,omitempty"`

@ -58,6 +58,9 @@ type ItemExtNet struct {
// CKey // CKey
CKey string `json:"_ckey"` CKey string `json:"_ckey"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Meta // Meta
Meta []interface{} `json:"_meta"` Meta []interface{} `json:"_meta"`
@ -166,6 +169,9 @@ type RecordExtNet struct {
// List excludes // List excludes
Excluded ListReservations `json:"excluded"` Excluded ListReservations `json:"excluded"`
// Enable Security Groups
EnableSecGroups bool `json:"enable_secgroups"`
// Free IPs number // Free IPs number
FreeIPs int64 `json:"free_ips"` FreeIPs int64 `json:"free_ips"`

@ -26,6 +26,10 @@ type UpdateRequest struct {
// Default: 1500 // Default: 1500
// Required: false // Required: false
MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty"` MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty"`
// Flag indicating whether security groups are enabled for this network
// Required: false
EnableSecGroups interface{} `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty" validate:"omitempty,isBool"`
} }
// Update updates external network parameters // Update updates external network parameters

@ -0,0 +1,41 @@
package image
import (
"context"
"net/http"
"strconv"
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
)
type ChangeStoragePolicyRequest struct {
// ID of the image to change the storage policy
// Required: true
ImageID uint64 `url:"image_id" json:"image_id" validate:"required"`
// ID of the storage policy to move the image to
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
}
// ChangeStoragePolicy changes the storage policy of the image chosen
func (i Image) ChangeStoragePolicy(ctx context.Context, req ChangeStoragePolicyRequest) (bool, error) {
err := validators.ValidateRequest(req)
if err != nil {
return false, validators.ValidationErrors(validators.GetErrors(err))
}
url := "/cloudbroker/image/change_storage_policy"
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil {
return false, err
}
result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
}

@ -18,6 +18,10 @@ type CreateCDROMImageRequest struct {
// Required: true // Required: true
URL string `url:"url" json:"url" validate:"required,url"` URL string `url:"url" json:"url" validate:"required,url"`
// ID of the chosen storage policy
// Required: true
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
// Account ID to make the image exclusive // Account ID to make the image exclusive
// Required: false // Required: false
AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"` AccountID uint64 `url:"accountId,omitempty" json:"accountId,omitempty"`
@ -37,11 +41,6 @@ type CreateCDROMImageRequest struct {
// Password for remote media download // Password for remote media download
// Required: false // Required: false
PasswordDl string `url:"passwordDL,omitempty" json:"passwordDL,omitempty"` PasswordDl string `url:"passwordDL,omitempty" json:"passwordDL,omitempty"`
// List of types of compute suitable for image.
// Example: [ "KVM_X86" ]
// Required: false
Drivers []string `url:"drivers,omitempty" json:"drivers,omitempty" validate:"max=2,imageDrivers"`
} }
// CreateCDROMImage creates CD-ROM image from an ISO identified by URL // CreateCDROMImage creates CD-ROM image from an ISO identified by URL

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save