1.5.8-k8s-extnet-branch
stSolo 2 years ago
parent 8712561853
commit d4b1ab7133

@ -0,0 +1,45 @@
## Version 1.0.0
### Features
- Add a configurable http-client for interacting with the DECORT cloud platform:
- Custom connection retries
- Custom auth method - app_id, app_secret pair and jwt-token
- Custom parameters for a ssl verify
- Custom SSO URL for auth
- Custom Decort URL for interacting with DECORT
- Add support for a cloudapi api groups:
- account
- bservice
- compute
- computeci
- disks
- extnet
- flipgroup
- image
- k8ci
- k8s
- kvmppc
- kvmx86
- lb
- locations
- rg
- sizes
- tasks
- vins
- Add support for a cloudbroker api groups:
- account
- compute
- disks
- extnet
- grid
- image
- k8ci
- k8s
- kvmppc
- kvmx86
- lb
- rg
- sep
- tasks
- vins

@ -0,0 +1,5 @@
.PHONY: lint
lint:
golangci-lint run --timeout 600s
.DEFAULT_GOAL := lint

@ -1,47 +1,427 @@
# Decort SDK # Decort SDK
## Install Decort SDK - это библиотека, написанная на языке GO, позволяющая взаимодействовать с API облачной платформы **DECORT**. Библиотека содеражит в себе структуры и методы, необходимые для отправки запросов. Decort SDK имеет встроенный http-клиент и поддерживает разные способы авторизации на платформе. Библиотека так же содержит в себе модели ответов от платформы.
## Оглавление
- [Установка](#установка)
- [Список API](#список-api)
- [Cloudapi](#cloudapi)
- [Cloudbroker](#cloudbroker)
- [Работа с библиотекой](#работа-с-библиотекой)
- [Настройка конфигурации клиента](#настройка-конфигурации-клиента)
- [Создание клиента](#создание-клиента)
- [Создание структуры запроса](#cоздание-структуры-запроса)
- [Выполнение запроса](#выполнение-запроса)
## Установка
Выполните команду в терминале:
```bash ```bash
go get -u github.com/rudecs/decort-sdk go get -u github.com/rudecs/decort-sdk
``` ```
## Example ## Список API
Библиотека поддерживает две группы API платформы:
- `cloudapi` - пользовательская группа, которая позволяет воспользоваться всем стардартным функционалом платформы;
- `cloudbroker` - административная группа, которая позволяет воспользоваться всем стандартным функционалом платформы и расширенными возможностями, включающими в себя управление пользователями, ресурсами, платформами размещения ресурсов и т.д.
### Cloudapi
`Cloudapi` позволяет выполнять запросы к группе пользовательских конечных точек
Данная группа ручек позволяет выполнять следующие операции в платформе:
- `Account` - управление аккаунтами - внутренними учетными записями платформы, которые являются владельцами вычислительных ресурсов;
- `BService` - управление группами виртуальных машин (computes);
- `Compute` - управление виртуальными машинами (индивидуально);
- `ComputeCI` - управление конвейром для создания виртуальных машин;
- `Disks` - управление виртуальными дисками;
- `ExtNet` - управление виртуальными сетями, отвечающими за внешний доступ;
- `FLIPgroup` - управление группами "плавающими" ip - адресами;
- `Image` - управление образами операционных систем;
- `K8CI` - управление конвейром для создания кластера;
- `K8S` - управление кластерами kubernetes;
- `KVMPPC` - создание виртуальной машины Power PC (IBM);
- `KVMx86` - создание виртуальной машины x86;
- `LB` - управление балансировщиками нагрузки;
- `Locations` - получение информации о grid площадки;
- `RG` - управление ресурсными группами аккаунта;
- `Sizes` - получение информации о потребляемых ресурсах виртуальными машинами и дисками;
- `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера);
- `VINS` - управление виртуальными изолированными сетями.
### Cloudbroker
`Cloudbroker` позволяет выполнять запросы к группе пользовательских конечных точек
Данная группа ручек позволяет выполнять следующие операции в платформе:
- `Account` - управление аккаунтами - внутренними учетными записями платформы, которые являются владельцами вычислительных ресурсов;
- `Compute` - управление виртуальными машинами (индивидуально);
- `Disks` - управление виртуальными дисками;
- `ExtNet` - управление виртуальными сетями, отвечающими за внешний доступ;
- `Grid` - управление площадками;
- `Image` - управление образами операционных систем;
- `K8CI` - управление конвейром для создания кластера;
- `K8S` - управление кластерами kubernetes;
- `KVMPPC` - создание виртуальной машины Power PC (IBM);
- `KVMx86` - создание виртуальной машины x86;
- `LB` - управление балансировщиками нагрузки;
- `RG` - управление ресурсными группами аккаунта;
- `SEP` - управление storage endpoint (sep);
- `Tasks` - получение информации о ходе выполнения асинхронных задач (например, создание кластера);
- `VINS` - управление виртуальными изолированными сетями.
## Работа с библиотекой
Алгоритм работы с библиотекой выглядит следующим образом:
1. Настройка конфигурации клиента.
2. Создание клиента.
3. Создание структуры запроса.
4. Выполнение запроса.
### Настройка конфигурации клиента
Сначала, необходимо создать переменную конфигурации клиента. Конфигурация состоит как из обязательных, так и необязательных полей.
| Поле | Тип | Обязательный | Описание |
| --- | --- | --- | --- |
| AppID | string | Да | app_id ключа для выполнения запросов |
| AppSecret | string | Да | app_secret ключ для выполнения запроса |
| SSOURL | string | Да | URL адрес сервиса аутентификации и авторизации |
| DecortURL | string | Да | URL адрес платформы, с которой будет осуществляться взаимодействие |
| Retries | uint | Нет | Кол-во неудачных попыток выполнения запроса, по умолчанию - 5 |
| SSLSkipVerify | bool | Нет | Пропуск проверки подлинности сертификата, по умолчанию - true |
| Token | string | Нет | JWT токен |
Пример кода:
```go
import (
"github.com/rudecs/decort-sdk/config"
)
func main(){
// Настройка конфигурации
cfg := config.Config{
AppID: "<APP_ID>",
AppSecret: "<APP_SECRET>",
SSOURL: "https://sso.digitalenergy.online",
DecortURL: "https://mr4.digitalenergy.online",
Retries: 5,
}
}
```
### Создание клиента
Создание клиента происходит с помощью функции-строителя `New` из основного пакета `decort-sdk`, для избежания проблем с именами, пакету можно присвоить алиас `decort`. Функция принимает конфигурацию, возвращает структуру `DecortClient`, с помощью которой можно взаимодействовать с платформой.
### Пример
```go ```go
package main package main
import ( import (
"context" "github.com/rudecs/decort-sdk/config"
"fmt" decort "github.com/rudecs/decort-sdk"
"log" )
func main() {
// Настройка конфигурации
cfg := config.Config{
AppID: "<APPID>",
AppSecret: "<APPSECRET>",
SSOURL: "https://sso.digitalenergy.online",
DecortURL: "https://mr4.digitalenergy.online",
Retries: 5,
}
// Создание клиента
client := decort.New(cfg)
}
```
### Создание структуры запроса
Структуры запросов определены в пакетах:
- `pkg/cloudapi` - для `cloudapi`
- `pkg/cloudbroker` - для `cloudbroker`
В каждом пакете находятся пакеты групп API:
- **cloudapi**:
- `pkg/cloudapi/account` - для `Account`
- `pkg/cloudapi/bservice` - для `Basic Service`
- `pkg/cloudapi/compute` - для `Compute`
- `pkg/cloudapi/computeci` - для `ComputeCI`
- `pkg/cloudapi/disks` - для `Disks`
- `pkg/cloudapi/extnet` - для `ExtNet`
- `pkg/cloudapi/flipgroup` - для `FLIPGroup`
- `pkg/cloudapi/image` - для `Image`
- `pkg/cloudapi/k8ci` - для `K8CI`
- `pkg/cloudapi/k8s` - для `K8S`
- `pkg/cloudapi/kvmppc` - для `KVMPPC`
- `pkg/cloudapi/kvmx86` - для `KVMX86`
- `pkg/cloudapi/lb` - для `LB`
- `pkg/cloudapi/locations` - для `Locations`
- `pkg/cloudapi/rg` - для `RG`
- `pkg/cloudapi/sizes` - для `RG`
- `pkg/cloudapi/tasks` - для `Tasks`
- `pkg/cloudapi/vins` - для `VINS`
- **cloudbroker**:
- `pkg/cloudbroker/account` - для `Account`
- `pkg/cloudbroker/compute` - для `Compute`
- `pkg/cloudbroker/disks` - для `Disks`
- `pkg/cloudbroker/extnet` - для `ExtNet`
- `pkg/cloudbroker/grid` - для `Grid`
- `pkg/cloudbroker/image` - для `Image`
- `pkg/cloudbroker/k8ci` - для `K8CI`
- `pkg/cloudbroker/k8s` - для `K8S`
- `pkg/cloudbroker/kvmppc` - для `KVMPPC`
- `pkg/cloudbroker/kvmx86` - для `KVMX86`
- `pkg/cloudbroker/lb` - для `LB`
- `pkg/cloudbroker/rg` - для `RG`
- `pkg/cloudbroker/sep` - для `SEP`
- `pkg/cloudbroker/tasks` - для `Tasks`
- `pkg/cloudbroker/vins` - для `VINS`
Все поля структуры имеют описание, в которых содержится:
- Их назначение;
- Обязательный или нет - поле required в комментариях;
- Доп. информация (допустимые значения, значения по умолчанию).
#### Пример комментарие структуры
```go
type CreateRequest struct {
// ID of the resource group, which will own this VM
// Required: true
RGID uint64 `url:"rgId"`
// Name of this VM.
// Must be unique among all VMs (including those in DELETED state) in target resource group
// Required: true
Name string `url:"name"`
// Number CPUs to allocate to this VM
// Required: true
CPU uint64 `url:"cpu"`
// Volume of RAM in MB to allocate to this VM
// Required: true
RAM uint64 `url:"ram"`
// ID of the OS image to base this VM on;
// Could be boot disk image or CD-ROM image
// Required: true
ImageID uint64 `url:"imageId"`
// Size of the boot disk in GB
// Required: false
BootDisk uint64 `url:"bootDisk,omitempty"`
// ID of SEP to create boot disk on.
// Uses images SEP ID if not set
// Required: false
SEPID uint64 `url:"sepId,omitempty"`
// Pool to use if SEP ID is set, can be also empty if needed to be chosen by system
// Required: false
Pool string `url:"pool,omitempty"`
"github.com/rudecs/decort-sdk/config" // Network type
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86" // Should be one of:
// - VINS
// - EXTNET
// - NONE
// Required: false
NetType string `url:"netType,omitempty"`
// Network ID for connect to,
// for EXTNET - external network ID,
// for VINS - VINS ID,
// when network type is not "NONE"
// Required: false
NetID uint64 `url:"netId,omitempty"`
// IP address to assign to this VM when connecting to the specified network
// Required: false
IPAddr string `url:"ipAddr,omitempty"`
// Input data for cloud-init facility
// Required: false
Userdata string `url:"userdata,omitempty"`
// Text description of this VM
// Required: false
Description string `url:"desc,omitempty"`
// Start VM upon success
// Required: false
Start bool `url:"start,omitempty"`
// Stack ID
// Required: false
StackID uint64 `url:"stackId,omitempty"`
// System name
// Required: false
IS string `url:"IS,omitempty"`
// Compute purpose
// Required: false
IPAType string `url:"ipaType,omitempty"`
// Reason for action
// Required: false
Reason string `url:"reason,omitempty"`
}
```
#### Пример создания запроса для развертывания виртуальной машины:
```go
package main
import (
"github.com/rudecs/decort-sdk/config"
decort "github.com/rudecs/decort-sdk"
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86"
) )
func main() { func main() {
cfg := config.Config{ // Настройка конфигурации
AppID: "<APPID>", cfg := config.Config{
AppSecret: "<APPSECRET>", AppID: "<APPID>",
SSOURL: "https://sso.digitalenergy.online", AppSecret: "<APPSECRET>",
DecortURL: "https://mr4.digitalenergy.online", SSOURL: "https://sso.digitalenergy.online",
Retries: 5, DecortURL: "https://mr4.digitalenergy.online",
} Retries: 5,
client := decort.New(cfg) }
req := kvmx86.CreateRequest{
RGID: 123, // Создание клиента
Name: "compute", client := decort.New(cfg)
CPU: 4,
RAM: 4096, // Создание структуры запроса
ImageID: 321, // CreateRequest - реквест на создание виртуальной машины
} req := kvmx86.CreateRequest{
RGID: 123,
res, err := client.KVMX86().Create(context.Background(), req) Name: "compute",
if err != nil { CPU: 4,
log.Fatal(err) RAM: 4096,
} ImageID: 321,
}
fmt.Println(res) }
```
### Выполнение запроса
Чтобы выполнить запрос, необходимо:
1. Вызвать у клиента метод, отвечаеющий за определение группы API для взаимодействия, это может быть `.CloudAPI()`, либо `.CloudBroker()`. Данные методы возвращаеют соответствующие структуры, с помощью которых можно соверать запросы.
2. Вызвать у возвращенной структуры метод, определяющий группу ручек для взаимодействия.
Доступные методы для `.CloudAPI()`:
- `.Account()` - для работы с `Account`
- `.BService()` - для работы с `BService`
- `.Compute()` - для работы с `Compute`
- `.ComputeCI()` - для работы с `ComputeCI`
- `.Disks()` - для работы с `Disks`
- `.ExtNet()` - для работы с `ExtNet`
- `.FLIPgroup()` - для работы с `FLIPGroup`
- `.Image()` - для работы с `Image`
- `.K8CI()` - для работы с `K8CI`
- `.K8S()` - для работы с `K8S`
- `.KVMPPC()` - для работы с `KVMPPC`
- `.KVMx86()` - для работы с `KVMX86`
- `.LB()` - для работы с `LB`
- `.Locations()` - для работы с `Locations`
- `.RG()` - для работы с `RG`
- `.Sizes()` - для работы с `Sizes`
- `.Tasks()` - для работы с `Tasks`
- `.VINS()` - для работы с `VINS`
Доступные методы для `.CloudBroker()`:
- `.Account()` - для работы с `Account`
- `.Compute()` - для работы с `Compute`
- `.Disks()` - для работы с `Disks`
- `.ExtNet()` - для работы с `ExtNet`
- `.Grid()` - для работы с `Grid`
- `.Image()` - для работы с `Image`
- `.K8CI()` - для работы с `K8CI`
- `.K8S()` - для работы с `K8S`
- `.KVMPPC()` - для работы с `KVMPPC`
- `.KVMx86()` - для работы с `KVMX86`
- `.LB()` - для работы с `LB`
- `.RG()` - для работы с `RG`
- `.SEP()` - для работы с `SEP`
- `.Tasks()` - для работы с `Tasks`
- `.VINS()` - для работы с `VINS`
3. Вызвать метод, отвечающий за выполнение запроса и передать в него:
- контекст;
- структуру запроса.
У кождой группы ручек API имеются свои доступные методы, которые определяются платформой.
4. Обработать результат и ошибки.
Т.к. все вызовы методов идут последовательно, можно их объеденить в конвейер:
Общий вид вонвейра будет выглядеть так:
```go
client.<API>.<группа>.<метод>
```
#### Пример выполнения запроса
```go
package main
import (
"log"
"fmt"
"github.com/rudecs/decort-sdk/config"
decort "github.com/rudecs/decort-sdk"
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86"
)
func main() {
// Настройка конфигурации
cfg := config.Config{
AppID: "<APPID>",
AppSecret: "<APPSECRET>",
SSOURL: "https://sso.digitalenergy.online",
DecortURL: "https://mr4.digitalenergy.online",
Retries: 5,
}
// Создание клиента
client := decort.New(cfg)
// Создание структуры запроса
// CreateRequest - реквест на создание виртуальной машины
req := kvmx86.CreateRequest{
RGID: 123,
Name: "compute",
CPU: 4,
RAM: 4096,
ImageID: 321,
}
//Выполнение запроса с помощью конвейера
res, err := client.СloudAPI().KVMX86().Create(context.Background(), req)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
} }
``` ```

@ -0,0 +1,62 @@
# Decort SDK
Decort SDK is a library, written in GO (Golang) for interact with the **DECORT** API.
The library contents structures and methods for requesting to an user (cloudapi) and admin (cloudbroker) groups of API.
Also the library have structures for responses.
## Contents
- [Install](#install)
- [API List](#api-list)
- [Examples](#examples)
- [Examples2](#examples2)
## Install
```bash
go get -u github.com/rudecs/decort-sdk
```
## API List
## Examples
```go
package main
import (
"context"
"fmt"
"log"
"github.com/rudecs/decort-sdk/config"
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86"
)
func main() {
cfg := config.Config{
AppID: "<APPID>",
AppSecret: "<APPSECRET>",
SSOURL: "https://sso.digitalenergy.online",
DecortURL: "https://mr4.digitalenergy.online",
Retries: 5,
}
client := decort.New(cfg)
req := kvmx86.CreateRequest{
RGID: 123,
Name: "compute",
CPU: 4,
RAM: 4096,
ImageID: 321,
}
res, err := client.KVMX86().Create(context.Background(), req)
if err != nil {
log.Fatal(err)
}
fmt.Println(res)
}
```
## Examples2

@ -15,31 +15,36 @@ import (
"github.com/rudecs/decort-sdk/internal/client" "github.com/rudecs/decort-sdk/internal/client"
) )
type Client struct { // HTTP-client for platform
type DecortClient struct {
decortURL string decortURL string
client *http.Client client *http.Client
} }
func New(cfg config.Config) *Client { // Сlient builder
func New(cfg config.Config) *DecortClient {
if cfg.Retries == 0 { if cfg.Retries == 0 {
cfg.Retries = 5 cfg.Retries = 5
} }
return &Client{ return &DecortClient{
decortURL: cfg.DecortURL, decortURL: cfg.DecortURL,
client: client.NewHttpClient(cfg), client: client.NewHttpClient(cfg),
} }
} }
func (dc *Client) CloudApi() *cloudapi.CloudApi { // CloudAPI builder
func (dc *DecortClient) CloudAPI() *cloudapi.CloudAPI {
return cloudapi.New(dc) return cloudapi.New(dc)
} }
func (dc *Client) CloudBroker() *cloudbroker.CloudBroker { // CloudBroker builder
func (dc *DecortClient) CloudBroker() *cloudbroker.CloudBroker {
return cloudbroker.New(dc) return cloudbroker.New(dc)
} }
func (dc *Client) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) { // DecortApiCall method for sending requests to the platform
func (dc *DecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
values, err := query.Values(params) values, err := query.Values(params)
if err != nil { if err != nil {
return nil, err return nil, err

@ -1,11 +1,39 @@
package config package config
// Configuration for creating request to platform
type Config struct { type Config struct {
Token string // JWT platform token
AppID string // Required: false
AppSecret string // Example: "qwqwdfwv68979we0q9bfv7e9sbvd89798qrwv97ff"
SSOURL string Token string
DecortURL string
Retries uint64 // Application (client) identifier for authorization
// in the cloud platform controller in oauth2 mode.
// Required: true
// Example: "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu"
AppID string
// Application (client) secret code for authorization
// in the cloud platform controller in oauth2 mode.
// Example: "frvet09rvesfis0c9erv9fsov0vsdfi09ovds0f"
AppSecret string
// Platform authentication service address
// Required: true
// Example: "https://sso.digitalenergy.online"
SSOURL string
// The address of the platform on which the actions are planned
// Required: true
// Example: "https://mr4.digitalenergy.online"
DecortURL string
// Amount platform request attempts
// Default value: 5
// Required: false
Retries uint64
// Skip verify, true by default
// Required: false
SSLSkipVerify bool SSLSkipVerify bool
} }

@ -2,6 +2,8 @@ package interfaces
import "context" import "context"
// Interface for sending requests to platform
type Caller interface { type Caller interface {
// 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)
} }

@ -4,6 +4,7 @@ import (
"github.com/rudecs/decort-sdk/pkg/cloudapi/account" "github.com/rudecs/decort-sdk/pkg/cloudapi/account"
) )
func (ca *CloudApi) Account() *account.Account { // Accessing the Account method group
func (ca *CloudAPI) Account() *account.Account {
return account.New(ca.client) return account.New(ca.client)
} }

@ -1,13 +1,16 @@
// API Actor API for managing account
package account package account
import ( import (
"github.com/rudecs/decort-sdk/interfaces" "github.com/rudecs/decort-sdk/interfaces"
) )
// Structure for creating request to account
type Account struct { type Account struct {
client interfaces.Caller client interfaces.Caller
} }
// Builder for account endpoints
func New(client interfaces.Caller) *Account { func New(client interfaces.Caller) *Account {
return &Account{ return &Account{
client, client,

@ -9,25 +9,34 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for adding permission to access to account for a user
type AddUserRequest struct { type AddUserRequest struct {
AccountID uint64 `url:"accountId"` // ID of account to add to
UserID string `url:"userId"` // Required: true
AccountID uint64 `url:"accountId"`
// Name of the user to be given rights
// Required: true
UserID string `url:"userId"`
// Account permission types:
// - 'R' for read only access
// - 'RCX' for Write
// - 'ARCXDU' for Admin
// Required: true
AccessType string `url:"accesstype"` AccessType string `url:"accesstype"`
} }
func (arq AddUserRequest) Validate() error { func (arq AddUserRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
if arq.UserID == "" { if arq.UserID == "" {
return errors.New("validation-error: field UserID can not be empty") return errors.New("validation-error: field UserID can not be empty")
} }
if arq.AccessType == "" { if arq.AccessType == "" {
return errors.New("validation-error: field AccessType can not be empty") return errors.New("validation-error: field AccessType can not be empty")
} }
isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"}) isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"})
if !isValid { if !isValid {
return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU")
@ -36,8 +45,9 @@ func (arq AddUserRequest) Validate() error {
return nil return nil
} }
// AddUser gives a user access rights.
func (a Account) AddUser(ctx context.Context, req AddUserRequest) (bool, error) { func (a Account) AddUser(ctx context.Context, req AddUserRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for give list account audits
type AuditsRequest struct { type AuditsRequest struct {
// ID of the account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq AuditsRequest) Validate() error { func (arq AuditsRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,25 +22,26 @@ func (arq AuditsRequest) Validate() error {
return nil return nil
} }
func (a Account) Audits(ctx context.Context, req AuditsRequest) (AccountAuditsList, error) { // Audits gets audit records for the specified account object
err := req.Validate() func (a Account) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
url := "/cloudapi/account/audits" url := "/cloudapi/account/audits"
auditsRaw, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
audits := AccountAuditsList{} list := ListAudits{}
err = json.Unmarshal(auditsRaw, &audits) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return audits, nil return list, nil
} }

@ -5,35 +5,87 @@ import (
"errors" "errors"
"net/http" "net/http"
"strconv" "strconv"
"github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for creating account
type CreateRequest struct { type CreateRequest struct {
Name string `url:"name"` // Display name
Username string `url:"username"` // Required: true
EmailAddress string `url:"emailaddress,omitempty"` Name string `url:"name"`
MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"`
MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"` // Name of the account
MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` // Required: true
Username string `url:"username"`
// Email
// Required: false
EmailAddress string `url:"emailaddress,omitempty"`
// Max size of memory in MB
// Required: false
MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"`
// Max size of aggregated vdisks in GB
// Required: false
MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"`
// Max number of CPU cores
// Required: false
MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"`
// Max sent/received network transfer peering
// Required: false
MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"`
MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"`
SendAccessEmails bool `url:"sendAccessEmails,omitempty"` // Max number of assigned public IPs
GPUUnits uint64 `url:"gpu_units,omitempty"` // Required: false
MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"`
// If true send emails when a user is granted access to resources
// Required: false
SendAccessEmails bool `url:"sendAccessEmails,omitempty"`
// Limit (positive) or disable (0) GPU resources
// Required: false
GPUUnits uint64 `url:"gpu_units,omitempty"`
// Resource types available to create in this account
// Each element in a resource type slice must be one of:
// - compute
// - vins
// - k8s
// - openshift
// - lb
// - flipgroup
// Required: false
ResTypes []string `url:"resourceTypes,omitempty"`
} }
func (arq CreateRequest) Validate() error { func (arq CreateRequest) validate() error {
if arq.Name == "" { if arq.Name == "" {
return errors.New("validation-error: field Name can not be empty") return errors.New("validation-error: field Name can not be empty")
} }
if arq.Username == "" { if arq.Username == "" {
return errors.New("validation-error: field Username can not be empty") return errors.New("validation-error: field Username can not be empty")
} }
if len(arq.ResTypes) > 0 {
for _, value := range arq.ResTypes {
validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"})
if !validate {
return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]")
}
}
}
return nil return nil
} }
// Create creates account
// 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) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return 0, err return 0, err
} }

@ -6,21 +6,27 @@ import (
"net/http" "net/http"
) )
// Request struct for delete account
type DeleteRequest struct { type DeleteRequest struct {
AccountID uint64 `url:"accountId"` // ID of account to delete
Permanently bool `url:"permanently,omitempty"` // Required: true
} AccountID uint64 `url:"accountId"`
func (arq DeleteRequest) Validate() error { // Whether to completely delete the account
// Required: false
Permanently bool `url:"permanently,omitempty"`
}
func (arq DeleteRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID must be set") return errors.New("validation-error: field AccountID must be set")
} }
return nil return nil
} }
// Delete completes delete an account from the system Returns true if account is deleted or was already deleted or never existed
func (a Account) Delete(ctx context.Context, req DeleteRequest) (bool, error) { func (a Account) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,17 +7,25 @@ import (
"strconv" "strconv"
) )
// Request struct for revoke access to account
type DeleteUserRequest struct { type DeleteUserRequest struct {
AccountID uint64 `url:"accountId"` // ID of the account
UserID string `url:"userId"` // Required: true
RecursiveDelete bool `url:"recursivedelete,omitempty"` AccountID uint64 `url:"accountId"`
// ID or emailaddress of the user to remove
// Required: true
UserID string `url:"userId"`
// Recursively revoke access rights from owned cloudspaces and vmachines
// Required: false
RecursiveDelete bool `url:"recursivedelete,omitempty"`
} }
func (arq DeleteUserRequest) Validate() error { func (arq DeleteUserRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
if arq.UserID == "" { if arq.UserID == "" {
return errors.New("validation-error: field UserID can not be empty") return errors.New("validation-error: field UserID can not be empty")
} }
@ -25,8 +33,9 @@ func (arq DeleteUserRequest) Validate() error {
return nil return nil
} }
// DeleteUser revokes user access from the account
func (a Account) DeleteUser(ctx context.Context, req DeleteUserRequest) (bool, error) { func (a Account) DeleteUser(ctx context.Context, req DeleteUserRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for change status of account
type DisabelEnableRequest struct { type DisabelEnableRequest struct {
// ID of account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq DisabelEnableRequest) Validate() error { func (arq DisabelEnableRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq DisabelEnableRequest) Validate() error {
return nil return nil
} }
// Disable disables an account
func (a Account) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) { func (a Account) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }
@ -40,8 +44,9 @@ func (a Account) Disable(ctx context.Context, req DisabelEnableRequest) (bool, e
return result, nil return result, nil
} }
// Enable enables an account
func (a Account) Enable(ctx context.Context, req DisabelEnableRequest) (bool, error) { func (a Account) Enable(ctx context.Context, req DisabelEnableRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get information about account
type GetRequest struct { type GetRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq GetRequest) Validate() error { func (arq GetRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq GetRequest) Validate() error {
return nil return nil
} }
func (a Account) Get(ctx context.Context, req GetRequest) (*AccountWithResources, error) { // Get gets account details
err := req.Validate() func (a Account) Get(ctx context.Context, req GetRequest) (*RecordAccount, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +36,13 @@ func (a Account) Get(ctx context.Context, req GetRequest) (*AccountWithResources
return nil, err return nil, err
} }
account := &AccountWithResources{} info := RecordAccount{}
err = json.Unmarshal(res, &account) err = json.Unmarshal(res, &info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return account, nil return &info, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for calculate the currently consumed units for all cloudspaces and resource groups in the account
type GetConsumedAccountUnitsRequest struct { type GetConsumedAccountUnitsRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq GetConsumedAccountUnitsRequest) Validate() error { func (arq GetConsumedAccountUnitsRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,14 @@ func (arq GetConsumedAccountUnitsRequest) Validate() error {
return nil return nil
} }
// GetConsumedAccountUnits calculates the currently consumed units for all cloudspaces and resource groups in the account.
// Calculated cloud units are returned in a dict which includes:
// - CU_M: consumed memory in MB
// - CU_C: number of cpu cores
// - CU_D: consumed vdisk storage in GB
// - CU_I: number of public IPs
func (a Account) GetConsumedAccountUnits(ctx context.Context, req GetConsumedAccountUnitsRequest) (*ResourceLimits, error) { func (a Account) GetConsumedAccountUnits(ctx context.Context, req GetConsumedAccountUnitsRequest) (*ResourceLimits, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +41,12 @@ func (a Account) GetConsumedAccountUnits(ctx context.Context, req GetConsumedAcc
return nil, err return nil, err
} }
rl := &ResourceLimits{} info := ResourceLimits{}
err = json.Unmarshal(res, &rl) err = json.Unmarshal(res, &info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return rl, nil return &info, nil
} }

@ -9,20 +9,24 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for calculate the currently consumed cloud units of the specified type for all cloudspaces and resource groups in the account
type GetConsumedCloudUnitsByTypeRequest struct { type GetConsumedCloudUnitsByTypeRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
CUType string `url:"cutype"`
// Cloud unit resource type
// Required: true
CUType string `url:"cutype"`
} }
func (arq GetConsumedCloudUnitsByTypeRequest) Validate() error { func (arq GetConsumedCloudUnitsByTypeRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
if arq.CUType == "" { if arq.CUType == "" {
return errors.New("validation-error: field CUType can not be empty") return errors.New("validation-error: field CUType can not be empty")
} }
isValid := validators.StringInSlice(arq.CUType, []string{"CU_M", "CU_C", "CU_D", "CU_S", "CU_A", "CU_NO", "CU_I", "CU_NP"}) isValid := validators.StringInSlice(arq.CUType, []string{"CU_M", "CU_C", "CU_D", "CU_S", "CU_A", "CU_NO", "CU_I", "CU_NP"})
if !isValid { if !isValid {
return errors.New("validation-error: field AccessType can be only CU_M, CU_C, CU_D, CU_S, CU_A, CU_NO, CU_I or CU_NP") return errors.New("validation-error: field AccessType can be only CU_M, CU_C, CU_D, CU_S, CU_A, CU_NO, CU_I or CU_NP")
@ -31,8 +35,20 @@ func (arq GetConsumedCloudUnitsByTypeRequest) Validate() error {
return nil return nil
} }
// GetConsumedCloudUnitsByType calculates the currently consumed cloud units of the specified type for all cloudspaces
// and resource groups in the account.
// Possible types of cloud units are include:
//
// - CU_M: returns consumed memory in MB
// - CU_C: returns number of virtual cpu cores
// - CU_D: returns consumed virtual disk storage in GB
// - CU_S: returns consumed primary storage (NAS) in TB
// - CU_A: returns consumed secondary storage (Archive) in TB
// - CU_NO: returns sent/received network transfer in operator in GB
// - CU_NP: returns sent/received network transfer peering in GB
// - CU_I: returns number of public IPs
func (a Account) GetConsumedCloudUnitsByType(ctx context.Context, req GetConsumedCloudUnitsByTypeRequest) (float64, error) { func (a Account) GetConsumedCloudUnitsByType(ctx context.Context, req GetConsumedCloudUnitsByTypeRequest) (float64, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -50,5 +66,4 @@ func (a Account) GetConsumedCloudUnitsByType(ctx context.Context, req GetConsume
} }
return result, nil return result, nil
} }

@ -6,21 +6,28 @@ import (
"net/http" "net/http"
) )
// Request struct for download the resources tracking files for an account
type GetConsumtionRequest struct { type GetConsumtionRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
Start uint64 `url:"start"`
End uint64 `url:"end"` // Epoch represents the start time
// Required: true
Start uint64 `url:"start"`
// Epoch represents the end time
// Required: true
End uint64 `url:"end"`
} }
func (arq GetConsumtionRequest) Validate() error { func (arq GetConsumtionRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
if arq.Start == 0 { if arq.Start == 0 {
return errors.New("validation-error: field Start can not be empty or equal to 0") return errors.New("validation-error: field Start can not be empty or equal to 0")
} }
if arq.End == 0 { if arq.End == 0 {
return errors.New("validation-error: field End can not be empty or equal to 0") return errors.New("validation-error: field End can not be empty or equal to 0")
} }
@ -28,8 +35,9 @@ func (arq GetConsumtionRequest) Validate() error {
return nil return nil
} }
// GetConsumtion downloads the resources tracking files for an account within a given period
func (a Account) GetConsumtion(ctx context.Context, req GetConsumtionRequest) (string, error) { func (a Account) GetConsumtion(ctx context.Context, req GetConsumtionRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }
@ -45,21 +53,19 @@ func (a Account) GetConsumtion(ctx context.Context, req GetConsumtionRequest) (s
} }
// GetConsumtionGet downloads the resources tracking files for an account within a given period
func (a Account) GetConsumtionGet(ctx context.Context, req GetConsumtionRequest) (string, error) { func (a Account) GetConsumtionGet(ctx context.Context, req GetConsumtionRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }
url := "/account/getConsumtion" url := "/cloudapi//account/getConsumtion"
prefix := "/cloudapi"
url = prefix + url
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req) res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
if err != nil { if err != nil {
return "", err return "", err
} }
return string(res), nil return string(res), nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for calculate the reserved units for all cloudspaces and resource groups in the account
type GetReservedAccountUnitsRequest struct { type GetReservedAccountUnitsRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq GetReservedAccountUnitsRequest) Validate() error { func (arq GetReservedAccountUnitsRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,15 @@ func (arq GetReservedAccountUnitsRequest) Validate() error {
return nil return nil
} }
// GetReservedAccountUnits calculates the reserved units for all cloudspaces and resource groups in the account.
// Calculated cloud units are returned in a dict which includes:
//
// - CU_M: reserved memory in MB
// - CU_C: number of cpu cores
// - CU_D: reserved vdisk storage in GB
// - CU_I: number of public IPs
func (a Account) GetReservedAccountUnits(ctx context.Context, req GetReservedAccountUnitsRequest) (*ResourceLimits, error) { func (a Account) GetReservedAccountUnits(ctx context.Context, req GetReservedAccountUnitsRequest) (*ResourceLimits, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +42,12 @@ func (a Account) GetReservedAccountUnits(ctx context.Context, req GetReservedAcc
return nil, err return nil, err
} }
rl := &ResourceLimits{} info := ResourceLimits{}
err = json.Unmarshal(res, &rl) err = json.Unmarshal(res, &info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return rl, nil return &info, nil
} }

@ -6,12 +6,19 @@ import (
"net/http" "net/http"
) )
// Request struct for get list of accounts
type ListRequest struct { type ListRequest struct {
// Page number
// Required: false
Page uint64 `url:"page"` Page uint64 `url:"page"`
// Page size
// Required: false
Size uint64 `url:"size"` Size uint64 `url:"size"`
} }
func (a Account) List(ctx context.Context, req ListRequest) (AccountCloudApiList, error) { // List gets list all accounts the user has access to
func (a Account) List(ctx context.Context, req ListRequest) (ListAccounts, error) {
url := "/cloudapi/account/list" url := "/cloudapi/account/list"
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
@ -19,13 +26,12 @@ func (a Account) List(ctx context.Context, req ListRequest) (AccountCloudApiList
return nil, err return nil, err
} }
accountList := AccountCloudApiList{} list := ListAccounts{}
err = json.Unmarshal(res, &accountList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for a get list compute instances
type ListComputesRequest struct { type ListComputesRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq ListComputesRequest) Validate() error { func (arq ListComputesRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq ListComputesRequest) Validate() error {
return nil return nil
} }
func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (AccountComputesList, error) { // ListComputes gets list all compute instances under specified account, accessible by the user
err := req.Validate() func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (ListComputes, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +36,12 @@ func (a Account) ListComputes(ctx context.Context, req ListComputesRequest) (Acc
return nil, err return nil, err
} }
accountComputesList := AccountComputesList{} list := ListComputes{}
err = json.Unmarshal(res, &accountComputesList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountComputesList, nil return list, nil
} }

@ -6,12 +6,19 @@ import (
"net/http" "net/http"
) )
// Request struct for get list deleted accounts
type ListDeletedRequest struct { type ListDeletedRequest struct {
// Page number
// Required: false
Page uint64 `url:"page"` Page uint64 `url:"page"`
// Page size
// Required: false
Size uint64 `url:"size"` Size uint64 `url:"size"`
} }
func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (AccountCloudApiList, error) { // ListDeleted gets list all deleted accounts the user has access to
func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListAccounts, error) {
url := "/cloudapi/account/listDeleted" url := "/cloudapi/account/listDeleted"
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
@ -19,13 +26,12 @@ func (a Account) ListDeleted(ctx context.Context, req ListDeletedRequest) (Accou
return nil, err return nil, err
} }
accountList := AccountCloudApiList{} list := ListAccounts{}
err = json.Unmarshal(res, &accountList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get list deleted disks
type ListDisksRequest struct { type ListDisksRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq ListDisksRequest) Validate() error { func (arq ListDisksRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq ListDisksRequest) Validate() error {
return nil return nil
} }
func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (AccountDisksList, error) { // ListDisks gets list all currently unattached disks under specified account
err := req.Validate() func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (ListDisks, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +36,12 @@ func (a Account) ListDisks(ctx context.Context, req ListDisksRequest) (AccountDi
return nil, err return nil, err
} }
accountDisksList := AccountDisksList{} list := ListDisks{}
err = json.Unmarshal(res, &accountDisksList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountDisksList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
type ListFlipGroupsRequest struct { // Request struct for get list FLIPGroups
type ListFLIPGroupsRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq ListFlipGroupsRequest) Validate() error { func (arq ListFLIPGroupsRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq ListFlipGroupsRequest) Validate() error {
return nil return nil
} }
func (a Account) ListFlipGroups(ctx context.Context, req ListFlipGroupsRequest) (AccountFlipGroupsList, error) { // ListFLIPGroups gets list all FLIPGroups under specified account, accessible by the user
err := req.Validate() func (a Account) ListFLIPGroups(ctx context.Context, req ListFLIPGroupsRequest) (ListFLIPGroups, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +36,12 @@ func (a Account) ListFlipGroups(ctx context.Context, req ListFlipGroupsRequest)
return nil, err return nil, err
} }
accountFlipGroupsList := AccountFlipGroupsList{} list := ListFLIPGroups{}
err = json.Unmarshal(res, &accountFlipGroupsList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountFlipGroupsList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get list resource groups
type ListRGRequest struct { type ListRGRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq ListRGRequest) Validate() error { func (arq ListRGRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq ListRGRequest) Validate() error {
return nil return nil
} }
func (a Account) ListRG(ctx context.Context, req ListRGRequest) (AccountRGList, error) { // ListRG gets list all resource groups under specified account, accessible by the user
err := req.Validate() func (a Account) ListRG(ctx context.Context, req ListRGRequest) (ListRG, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +36,12 @@ func (a Account) ListRG(ctx context.Context, req ListRGRequest) (AccountRGList,
return nil, err return nil, err
} }
accountRGList := AccountRGList{} list := ListRG{}
err = json.Unmarshal(res, &accountRGList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountRGList, nil return list, nil
} }

@ -7,12 +7,18 @@ import (
"net/http" "net/http"
) )
// Request struct for get list templates
type ListTemplatesRequest struct { type ListTemplatesRequest struct {
AccountID uint64 `url:"accountId"` // ID an account
IncludeDeleted bool `url:"includedeleted"` // Required: true
AccountID uint64 `url:"accountId"`
// Include deleted images
// Required: false
IncludeDeleted bool `url:"includedeleted"`
} }
func (arq ListTemplatesRequest) Validate() error { func (arq ListTemplatesRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -20,8 +26,9 @@ func (arq ListTemplatesRequest) Validate() error {
return nil return nil
} }
func (a Account) ListTemplates(ctx context.Context, req ListTemplatesRequest) (AccountTemplatesList, error) { // ListTemplates gets list templates which can be managed by this account
err := req.Validate() func (a Account) ListTemplates(ctx context.Context, req ListTemplatesRequest) (ListTemplates, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -33,13 +40,12 @@ func (a Account) ListTemplates(ctx context.Context, req ListTemplatesRequest) (A
return nil, err return nil, err
} }
accountTemplatesList := AccountTemplatesList{} list := ListTemplates{}
err = json.Unmarshal(res, &accountTemplatesList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountTemplatesList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get list VINS
type ListVINSRequest struct { type ListVINSRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq ListVINSRequest) Validate() error { func (arq ListVINSRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq ListVINSRequest) Validate() error {
return nil return nil
} }
func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (AccountVINSList, error) { // ListVINS gets list all ViNSes under specified account, accessible by the user
err := req.Validate() func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (ListVINS, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,13 +36,12 @@ func (a Account) ListVINS(ctx context.Context, req ListVINSRequest) (AccountVINS
return nil, err return nil, err
} }
accountVINSList := AccountVINSList{} list := ListVINS{}
err = json.Unmarshal(res, &accountVINSList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return accountVINSList, nil return list, nil
} }

@ -1,229 +1,547 @@
package account package account
type AccountACLRecord struct { // Access Control List
IsExplicit bool `json:"explicit"` type RecordACL struct {
GUID string `json:"guid"` // Whether access is explicitly specified
Rights string `json:"right"` IsExplicit bool `json:"explicit"`
Status string `json:"status"`
Type string `json:"type"` // GUID
UgroupID string `json:"userGroupId"` GUID string `json:"guid"`
CanBeDeleted bool `json:"canBeDeleted"`
// Access rights
Rights string `json:"right"`
// Status
Status string `json:"status"`
// Account Type
Type string `json:"type"`
// Account owner ID
UgroupID string `json:"userGroupId"`
// Is it possible to remove
CanBeDeleted bool `json:"canBeDeleted"`
} }
// Resource limits
type ResourceLimits struct { type ResourceLimits struct {
CUC float64 `json:"CU_C"` // Number of cores
CUD float64 `json:"CU_D"` CUC float64 `json:"CU_C"`
CUI float64 `json:"CU_I"`
CUM float64 `json:"CU_M"` // Disk size, GB
CUNP float64 `json:"CU_NP"` CUD float64 `json:"CU_D"`
// Number of public IP addresses
CUI float64 `json:"CU_I"`
// RAM size, MB
CUM float64 `json:"CU_M"`
// Traffic volume, GB
CUNP float64 `json:"CU_NP"`
// Number of graphics cores
GPUUnits float64 `json:"gpu_units"` GPUUnits float64 `json:"gpu_units"`
} }
type AccountRecord struct { // Main information of account
DCLocation string `json:"DCLocation"` type InfoAccount struct {
CKey string `jspn:"_ckey"` // Segment
Meta []interface{} `json:"_meta"` DCLocation string `json:"DCLocation"`
ACL []AccountACLRecord `json:"acl"`
Company string `json:"company"` // Key
CompanyURL string `json:"companyurl"` CKey string `jspn:"_ckey"`
CreatedBy string `jspn:"createdBy"`
CreatedTime uint64 `json:"createdTime"` // Meta
DeactiovationTime float64 `json:"deactivationTime"` Meta []interface{} `json:"_meta"`
DeletedBy string `json:"deletedBy"`
DeletedTime uint64 `json:"deletedTime"` // Access Control List
DisplayName string `json:"displayname"` ACL []RecordACL `json:"acl"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"` // Company
Name string `json:"name"` Company string `json:"company"`
ResourceLimits ResourceLimits `json:"resourceLimits"`
SendAccessEmails bool `json:"sendAccessEmails"` // Company URL
ServiceAccount bool `json:"serviceAccount"` CompanyURL string `json:"companyurl"`
Status string `json:"status"`
UpdatedTime uint64 `json:"updatedTime"` // Created by
Version uint64 `json:"version"` CreatedBy string `jspn:"createdBy"`
VINS []uint64 `json:"vins"`
} // Created time
CreatedTime uint64 `json:"createdTime"`
type AccountList []AccountRecord
// Deactiovation time
type AccountCloudApi struct { DeactiovationTime float64 `json:"deactivationTime"`
ACL []AccountACLRecord `json:"acl"`
CreatedTime uint64 `json:"createdTime"` // Deleted by
DeletedTime uint64 `json:"deletedTime"` DeletedBy string `json:"deletedBy"`
ID uint64 `json:"id"`
Name string `json:"name"` // Deleted time
Status string `json:"status"` DeletedTime uint64 `json:"deletedTime"`
UpdatedTime uint64 `json:"updatedTime"`
} // Display name
DisplayName string `json:"displayname"`
type AccountCloudApiList []AccountCloudApi
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
// Resource Limits
ResourceLimits ResourceLimits `json:"resourceLimits"`
// If true send emails when a user is granted access to resources
SendAccessEmails bool `json:"sendAccessEmails"`
// Service Account
ServiceAccount bool `json:"serviceAccount"`
// Status
Status string `json:"status"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// Version
Version uint64 `json:"version"`
// List VINS in account
VINS []uint64 `json:"vins"`
}
// Main information in one of if the list of accounts
type ItemAccount struct {
// Access Control List
ACL []RecordACL `json:"acl"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
// Status
Status string `json:"status"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
}
// List of accounts
type ListAccounts []ItemAccount
// Resources used
type Resource struct { type Resource struct {
CPU int64 `json:"cpu"` // Number of cores
DiskSize int64 `json:"disksize"` CPU int64 `json:"cpu"`
ExtIPs int64 `json:"extips"`
// Disk size
DiskSize int64 `json:"disksize"`
// Number of External IPs
ExtIPs int64 `json:"extips"`
// External traffic
ExtTraffic int64 `json:"exttraffic"` ExtTraffic int64 `json:"exttraffic"`
GPU int64 `json:"gpu"`
RAM int64 `json:"ram"` // Number of grafic cores
GPU int64 `json:"gpu"`
// Number of RAM
RAM int64 `json:"ram"`
} }
// Information about resources
type Resources struct { type Resources struct {
Current Resource `json:"Current"` // Current information about resources
Current Resource `json:"Current"`
// Reserved information about resources
Reserved Resource `json:"Reserved"` Reserved Resource `json:"Reserved"`
} }
// Information about computes
type Computes struct { type Computes struct {
// Number of started computes
Started uint64 `json:"started"` Started uint64 `json:"started"`
// Number of stopped computes
Stopped uint64 `json:"stopped"` Stopped uint64 `json:"stopped"`
} }
// Information about machines
type Machines struct { type Machines struct {
// Number of running machines
Running uint64 `json:"running"` Running uint64 `json:"running"`
Halted uint64 `json:"halted"`
// Number of halted machines
Halted uint64 `json:"halted"`
} }
type AccountWithResources struct { // Сomplete information about account
Account type RecordAccount struct {
// Main information about account
InfoAccount
// Resources
Resources Resources `json:"Resources"` Resources Resources `json:"Resources"`
Computes Computes `json:"computes"`
Machines Machines `json:"machines"` // Computes
VINSes uint64 `json:"vinses"` Computes Computes `json:"computes"`
}
// Machines
type AccountCompute struct { Machines Machines `json:"machines"`
AccountID uint64 `json:"accountId"`
AccountName string `json:"accountName"` // Number of VINSes
CPUs uint64 `json:"cpus"` VINSes uint64 `json:"vinses"`
CreatedBy string `json:"createdBy"` }
CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"` // Main information about compute
DeletedTime uint64 `json:"deletedTime"` type ItemCompute struct {
ComputeID uint64 `json:"id"` // ID an account
ComputeName string `json:"name"` AccountID uint64 `json:"accountId"`
RAM uint64 `json:"ram"`
Registered bool `json:"registered"` // Account name
RGID uint64 `json:"rgId"` AccountName string `json:"accountName"`
RGName string `json:"rgName"`
Status string `json:"status"` // Number of CPU
TechStatus string `json:"techStatus"` CPUs uint64 `json:"cpus"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// ID compute
ComputeID uint64 `json:"id"`
// Compute name
ComputeName string `json:"name"`
// Number of RAM
RAM uint64 `json:"ram"`
// Registered or not
Registered bool `json:"registered"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group Name
RGName string `json:"rgName"`
// Status
Status string `json:"status"`
// Tech status
TechStatus string `json:"techStatus"`
// Total disks size
TotalDisksSize uint64 `json:"totalDisksSize"` TotalDisksSize uint64 `json:"totalDisksSize"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime uint64 `json:"updatedTime"` // Updated by
UserManaged bool `json:"userManaged"` UpdatedBy string `json:"updatedBy"`
VINSConnected uint64 `json:"vinsConnected"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// User controlled or not
UserManaged bool `json:"userManaged"`
// Number of connected VINS
VINSConnected uint64 `json:"vinsConnected"`
} }
type AccountComputesList []AccountCompute // List of computes
type ListComputes []ItemCompute
// Main information about disk
type ItemDisk struct {
// ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
type AccountDisk struct { // Pool
ID uint64 `json:"id"` Pool string `json:"pool"`
Name string `json:"name"`
Pool string `json:"pool"` // ID SEP
SepID uint64 `json:"sepId"` SEPID uint64 `json:"sepId"`
// Max size
SizeMax uint64 `json:"sizeMax"` SizeMax uint64 `json:"sizeMax"`
Type string `json:"type"`
// Disk type
Type string `json:"type"`
} }
type AccountDisksList []AccountDisk // List of disks
type ListDisks []ItemDisk
type AccountVIN struct { // Main information about VINS
AccountID uint64 `json:"accountId"` type ItemVINS struct {
// Account ID
AccountID uint64 `json:"accountId"`
// Name of account
AccountName string `json:"accountName"` AccountName string `json:"accountName"`
Computes uint64 `json:"computes"`
CreatedBy string `json:"createdBy"` // Number of computes
Computes uint64 `json:"computes"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"` CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"` DeletedTime uint64 `json:"deletedTime"`
ExternalIP string `json:"externalIP"`
ID uint64 `json:"id"` // External IP
Name string `json:"name"` ExternalIP string `json:"externalIP"`
Network string `json:"network"`
PriVnfDevID uint64 `json:"priVnfDevId"` // ID
RGID uint64 `json:"rgId"` ID uint64 `json:"id"`
RGName string `json:"rgName"`
Status string `json:"status"` // Name
UpdatedBy string `json:"updatedBy"` Name string `json:"name"`
// Network
Network string `json:"network"`
// NNFDev ID
PriVNFDevID uint64 `json:"priVnfDevId"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// Status
Status string `json:"status"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"` UpdatedTime uint64 `json:"updatedTime"`
} }
type AccountVINSList []AccountVIN // List of VINS
type ListVINS []ItemVINS
// Main info about audit
type ItemAudit struct {
// Call
Call string `json:"call"`
type AccountAudit struct { // Response time
Call string `json:"call"`
ResponseTime float64 `json:"responsetime"` ResponseTime float64 `json:"responsetime"`
StatusCode uint64 `json:"statuscode"`
Timestamp float64 `json:"timestamp"` // Status code
User string `json:"user"` StatusCode uint64 `json:"statuscode"`
// Timestamp
Timestamp float64 `json:"timestamp"`
// User
User string `json:"user"`
} }
type AccountAuditsList []AccountAudit // List of audits
type ListAudits []ItemAudit
// Information compute in resource group
type RGComputes struct {
// Number of started computes
Started uint64 `json:"started"`
type AccountRGComputes struct { // Number of stopped computes
Started uint64 `json:"Started"` Stopped uint64 `json:"stopped"`
Stopped uint64 `json:"Stopped"`
} }
type AccountRGResources struct { // Resources of Resource group
type RGResources struct {
// Consumed
Consumed Resource `json:"Consumed"` Consumed Resource `json:"Consumed"`
Limits Resource `json:"Limits"`
// Limits
Limits Resource `json:"Limits"`
// Reserved
Reserved Resource `json:"Reserved"` Reserved Resource `json:"Reserved"`
} }
type AccountRG struct { // Main information about resource group
Computes AccountRGComputes `json:"Computes"` type ItemRG struct {
Resources AccountRGResources `json:"Resources"` // Computes
CreatedBy string `json:"createdBy"` Computes RGComputes `json:"Computes"`
CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"` // Resources
DeletedTime uint64 `json:"deletedTime"` Resources RGResources `json:"Resources"`
RGID uint64 `json:"id"`
Milestones uint64 `json:"milestones"` // Created by
RGName string `json:"name"` CreatedBy string `json:"createdBy"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"` // Created time
UpdatedTime uint64 `json:"updatedTime"` CreatedTime uint64 `json:"createdTime"`
VINSes uint64 `json:"vinses"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// Resource group ID
RGID uint64 `json:"id"`
// Milestones
Milestones uint64 `json:"milestones"`
// Resource group name
RGName string `json:"name"`
// Status
Status string `json:"status"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// Number of VINS
VINSes uint64 `json:"vinses"`
} }
type AccountRGList []AccountRG // List of Resource groups
type ListRG []ItemRG
// Main information about template
type ItemTemplate struct {
// UNCPath
UNCPath string `json:"UNCPath"`
// Account ID
AccountID uint64 `json:"accountId"`
type AccountTemplate struct { // Description
UNCPath string `json:"UNCPath"`
AccountID uint64 `json:"accountId"`
Description string `json:"desc"` Description string `json:"desc"`
ID uint64 `json:"id"`
Name string `json:"name"` // ID
Public bool `json:"public"` ID uint64 `json:"id"`
Size uint64 `json:"size"`
Status string `json:"status"` // Name
Type string `json:"type"` Name string `json:"name"`
Username string `json:"username"`
} // Public or not
Public bool `json:"public"`
type AccountTemplatesList []AccountTemplate
// Size
type AccountFlipGroup struct { Size uint64 `json:"size"`
AccountID uint64 `json:"accountId"`
ClientType string `json:"clientType"` // Status
ConnType string `json:"connType"` Status string `json:"status"`
CreatedBy string `json:"createdBy"`
// Type
Type string `json:"type"`
// Username
Username string `json:"username"`
}
// List of templates
type ListTemplates []ItemTemplate
// Main information about FLIPGroup
type ItemFLIPGroup struct {
// Account ID
AccountID uint64 `json:"accountId"`
// Client type
ClientType string `json:"clientType"`
// Connection type
ConnType string `json:"connType"`
// Created by
CreatedBy string `json:"createdBy"`
// Created time
CreatedTime uint64 `json:"createdTime"` CreatedTime uint64 `json:"createdTime"`
DefaultGW string `json:"defaultGW"`
DeletedBy string `json:"deletedBy"` // Default GW
DefaultGW string `json:"defaultGW"`
// Deleted by
DeletedBy string `json:"deletedBy"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"` DeletedTime uint64 `json:"deletedTime"`
// Description
Description string `json:"desc"` Description string `json:"desc"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"` // Grid ID
ID uint64 `json:"id"` GID uint64 `json:"gid"`
IP string `json:"ip"`
Milestones uint64 `json:"milestones"` // GUID
Name string `json:"name"` GUID uint64 `json:"guid"`
NetID uint64 `json:"netId"`
NetType string `json:"netType"` // ID
NetMask uint64 `json:"netmask"` ID uint64 `json:"id"`
Status string `json:"status"`
UpdatedBy string `json:"updatedBy"` // IP
IP string `json:"ip"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Network ID
NetID uint64 `json:"netId"`
// Network type
NetType string `json:"netType"`
// Network mask
NetMask uint64 `json:"netmask"`
// Status
Status string `json:"status"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"` UpdatedTime uint64 `json:"updatedTime"`
} }
type AccountFlipGroupsList []AccountFlipGroup // List of FLIPGroups
type ListFLIPGroups []ItemFLIPGroup

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for restore a deleted account
type RestoreRequest struct { type RestoreRequest struct {
// ID an account
// Required: true
AccountID uint64 `url:"accountId"` AccountID uint64 `url:"accountId"`
} }
func (arq RestoreRequest) Validate() error { func (arq RestoreRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (arq RestoreRequest) Validate() error {
return nil return nil
} }
// Restore restores a deleted account
func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error) { func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }
@ -38,5 +42,4 @@ func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error)
} }
return result, nil return result, nil
} }

@ -5,30 +5,79 @@ import (
"errors" "errors"
"net/http" "net/http"
"strconv" "strconv"
"github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for updaate account
type UpdateRequest struct { type UpdateRequest struct {
AccountID uint64 `url:"accountId"` // ID an account
Name string `url:"name,omitempty"` // Required: true
MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"` AccountID uint64 `url:"accountId"`
MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"`
MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"` // Name of the account
// Required: false
Name string `url:"name,omitempty"`
// Max size of memory in MB
// Required: false
MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty"`
// Max size of aggregated vdisks in GB
// Required: false
MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty"`
// Max number of CPU cores
// Required: false
MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty"`
// Max sent/received network transfer peering
// Required: false
MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"` MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty"`
MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"`
SendAccessEmails bool `url:"sendAccessEmails,omitempty"` // Max number of assigned public IPs
GPUUnits uint64 `url:"gpu_units,omitempty"` // Required: false
MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty"`
// If true send emails when a user is granted access to resources
// Required: false
SendAccessEmails bool `url:"sendAccessEmails,omitempty"`
// Limit (positive) or disable (0) GPU resources
// Required: false
GPUUnits uint64 `url:"gpu_units,omitempty"`
// Resource types available to create in this account
// Each element in a resource type slice must be one of:
// - compute
// - vins
// - k8s
// - openshift
// - lb
// - flipgroup
// Required: false
ResTypes []string `url:"resourceTypes,omitempty"`
} }
func (arq UpdateRequest) Validate() error { func (arq UpdateRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
if len(arq.ResTypes) > 0 {
for _, value := range arq.ResTypes {
validate := validators.StringInSlice(value, []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"})
if !validate {
return errors.New("validation-error: Every resource type specified should be one of [compute, vins, k8s, openshift, lb, flipgroup]")
}
}
}
return nil return nil
} }
// Update updates an account name and resource types and limits
func (a Account) Update(ctx context.Context, req UpdateRequest) (bool, error) { func (a Account) Update(ctx context.Context, req UpdateRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -9,25 +9,34 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for update user access rights
type UpdateUserRequest struct { type UpdateUserRequest struct {
AccountID uint64 `url:"accountId"` // ID of the account
UserID string `url:"userId"` // Required: true
AccountID uint64 `url:"accountId"`
// Userid/Email for registered users or emailaddress for unregistered users
// Required: true
UserID string `url:"userId"`
// Account permission types:
// - 'R' for read only access
// - 'RCX' for Write
// - 'ARCXDU' for Admin
// Required: true
AccessType string `url:"accesstype"` AccessType string `url:"accesstype"`
} }
func (arq UpdateUserRequest) Validate() error { func (arq UpdateUserRequest) validate() error {
if arq.AccountID == 0 { if arq.AccountID == 0 {
return errors.New("validation-error: field AccountID can not be empty or equal to 0") return errors.New("validation-error: field AccountID can not be empty or equal to 0")
} }
if arq.UserID == "" { if arq.UserID == "" {
return errors.New("validation-error: field UserID can not be empty") return errors.New("validation-error: field UserID can not be empty")
} }
if arq.AccessType == "" { if arq.AccessType == "" {
return errors.New("validation-error: field AccessType can not be empty") return errors.New("validation-error: field AccessType can not be empty")
} }
isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"}) isValid := validators.StringInSlice(arq.AccessType, []string{"R", "RCX", "ARCXDU"})
if !isValid { if !isValid {
return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU") return errors.New("validation-error: field AccessType can be only R, RCX or ARCXDU")
@ -36,8 +45,9 @@ func (arq UpdateUserRequest) Validate() error {
return nil return nil
} }
// UpdateUser updates user access rights
func (a Account) UpdateUser(ctx context.Context, req UpdateUserRequest) (bool, error) { func (a Account) UpdateUser(ctx context.Context, req UpdateUserRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -0,0 +1,8 @@
package cloudapi
import "github.com/rudecs/decort-sdk/pkg/cloudapi/bservice"
// Accessing the BService method group
func (ca *CloudAPI) BService() *bservice.BService {
return bservice.New(ca.client)
}

@ -1,11 +1,14 @@
// API Actor for managing Compute Group. This actor is a final API for endusers to manage Compute Group
package bservice package bservice
import "github.com/rudecs/decort-sdk/interfaces" import "github.com/rudecs/decort-sdk/interfaces"
// Structure for creating request to bservice
type BService struct { type BService struct {
client interfaces.Caller client interfaces.Caller
} }
// Builder for bservice endpoints
func New(client interfaces.Caller) *BService { func New(client interfaces.Caller) *BService {
return &BService{ return &BService{
client, client,

@ -7,18 +7,29 @@ import (
"strconv" "strconv"
) )
// Request struct for BasicService
type CreateRequest struct { type CreateRequest struct {
Name string `url:"name"` // Name of the service
RGID uint64 `url:"rgId"` // Required: true
Name string `url:"name"`
// ID of the Resource Group where this service will be placed
// Required: true
RGID uint64 `url:"rgId"`
// Name of the user to deploy SSH key for. Pass empty string if no SSH key deployment is required
// Required: false
SSHUser string `url:"sshUser,omitempty"` SSHUser string `url:"sshUser,omitempty"`
SSHKey string `url:"sshKey,omitempty"`
// SSH key to deploy for the specified user. Same key will be deployed to all computes of the service
// Required: false
SSHKey string `url:"sshKey,omitempty"`
} }
func (bsrq CreateRequest) Validate() error { func (bsrq CreateRequest) validate() error {
if bsrq.Name == "" { if bsrq.Name == "" {
return errors.New("field Name can not be empty") return errors.New("field Name can not be empty")
} }
if bsrq.RGID == 0 { if bsrq.RGID == 0 {
return errors.New("field RGID can not be empty or equal to 0") return errors.New("field RGID can not be empty or equal to 0")
} }
@ -26,16 +37,24 @@ func (bsrq CreateRequest) Validate() error {
return nil return nil
} }
// Create creates blank BasicService instance
func (b BService) Create(ctx context.Context, req CreateRequest) (uint64, error) { func (b BService) Create(ctx context.Context, req CreateRequest) (uint64, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return 0, err return 0, err
} }
url := "/cloudapi/bservice/create" url := "/cloudapi/bservice/create"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return strconv.ParseUint(string(res), 10, 64) result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
} }

@ -7,12 +7,18 @@ import (
"strconv" "strconv"
) )
// Request struct for delete basic service
type DeleteRequest struct { type DeleteRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the BasicService to be delete
Permanently bool `url:"permanently,omitempty"` // Required: true
ServiceID uint64 `url:"serviceId"`
// If set to False, Basic service will be deleted to recycle bin. Otherwise destroyed immediately
// Required: true
Permanently bool `url:"permanently,omitempty"`
} }
func (bsrq DeleteRequest) Validate() error { func (bsrq DeleteRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -20,16 +26,24 @@ func (bsrq DeleteRequest) Validate() error {
return nil return nil
} }
// Delete deletes BasicService instance
func (b BService) Delete(ctx context.Context, req DeleteRequest) (bool, error) { func (b BService) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/delete" url := "/cloudapi/bservice/delete"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for disable service
type DisableRequest struct { type DisableRequest struct {
// ID of the service to disable
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq DisableRequest) Validate() error { func (bsrq DisableRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,16 +22,26 @@ func (bsrq DisableRequest) Validate() error {
return nil return nil
} }
// Disable disables service.
// Disabling a service technically means setting model status
// of all computes and service itself to DISABLED and stopping all computes.
func (b BService) Disable(ctx context.Context, req DisableRequest) (bool, error) { func (b BService) Disable(ctx context.Context, req DisableRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/delete" url := "/cloudapi/bservice/delete"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for disable service
type EnableRequest struct { type EnableRequest struct {
// ID of the service to enable
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq EnableRequest) Validate() error { func (bsrq EnableRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,16 +22,27 @@ func (bsrq EnableRequest) Validate() error {
return nil return nil
} }
// Enable enables service.
// Enabling a service technically means setting model status of
// all computes and service itself to ENABLED.
// It does not start computes.
func (b BService) Enable(ctx context.Context, req EnableRequest) (bool, error) { func (b BService) Enable(ctx context.Context, req EnableRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/enable" url := "/cloudapi/bservice/enable"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get detailed information about service
type GetRequest struct { type GetRequest struct {
// ID of the service to query information
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq GetRequest) Validate() error { func (bsrq GetRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,21 +22,26 @@ func (bsrq GetRequest) Validate() error {
return nil return nil
} }
func (b BService) Get(ctx context.Context, req GetRequest) (*BasicService, error) { // Get gets detailed specifications for the BasicService.
if err := req.Validate(); err != nil { func (b BService) Get(ctx context.Context, req GetRequest) (*RecordBasicService, error) {
err := req.validate()
if err != nil {
return nil, err return nil, err
} }
url := "/cloudapi/bservice/get" url := "/cloudapi/bservice/get"
bsRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) bsRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bs := &BasicService{} info := RecordBasicService{}
if err := json.Unmarshal(bsRaw, bs); err != nil {
err = json.Unmarshal(bsRaw, &info)
if err != nil {
return nil, err return nil, err
} }
return bs, nil return &info, nil
} }

@ -7,50 +7,82 @@ import (
"strconv" "strconv"
) )
// Request struct for create new compute group within BasicService
type GroupAddRequest struct { type GroupAddRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service to add a group to
Name string `url:"name"` // Required: true
Count uint64 `url:"count"` ServiceID uint64 `url:"serviceId"`
CPU uint64 `url:"cpu"`
RAM uint64 `url:"ram"` // Name of the Compute Group to add
Disk uint64 `url:"disk"` // Required: true
ImageID uint64 `url:"imageId"` Name string `url:"name"`
Driver string `url:"driver"`
Role string `url:"role,omitempty"` // Computes number. Defines how many computes must be there in the group
VINSes []uint64 `url:"vinses,omitempty"` // Required: true
ExtNets []uint64 `url:"extnets,omitempty"` Count uint64 `url:"count"`
TimeoutStart uint64 `url:"timeoutStart"`
// Compute CPU number. All computes in the group have the same CPU count
// Required: true
CPU uint64 `url:"cpu"`
// Compute RAM volume in MB. All computes in the group have the same RAM volume
// Required: true
RAM uint64 `url:"ram"`
// Compute boot disk size in GB
// Required: true
Disk uint64 `url:"disk"`
// OS image ID to create computes from
// Required: true
ImageID uint64 `url:"imageId"`
// Compute driver
// should be one of:
// - KVM_X86
// - KVM_PPC
// Required: true
Driver string `url:"driver"`
// Group role tag. Can be empty string, does not have to be unique
// Required: false
Role string `url:"role,omitempty"`
// List of ViNSes to connect computes to
// Required: false
VINSes []uint64 `url:"vinses,omitempty"`
// List of external networks to connect computes to
// Required: false
ExtNets []uint64 `url:"extnets,omitempty"`
// Time of Compute Group readiness
// Required: false
TimeoutStart uint64 `url:"timeoutStart"`
} }
func (bsrq GroupAddRequest) Validate() error { func (bsrq GroupAddRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.Name == "" { if bsrq.Name == "" {
return errors.New("field Name can not be empty") return errors.New("field Name can not be empty")
} }
if bsrq.Count == 0 { if bsrq.Count == 0 {
return errors.New("field Count can not be empty or equal to 0") return errors.New("field Count can not be empty or equal to 0")
} }
if bsrq.CPU == 0 { if bsrq.CPU == 0 {
return errors.New("field CPU can not be empty or equal to 0") return errors.New("field CPU can not be empty or equal to 0")
} }
if bsrq.RAM == 0 { if bsrq.RAM == 0 {
return errors.New("field RAM can not be empty or equal to 0") return errors.New("field RAM can not be empty or equal to 0")
} }
if bsrq.Disk == 0 { if bsrq.Disk == 0 {
return errors.New("field Disk can not be empty or equal to 0") return errors.New("field Disk can not be empty or equal to 0")
} }
if bsrq.ImageID == 0 { if bsrq.ImageID == 0 {
return errors.New("field ImageID can not be empty or equal to 0") return errors.New("field ImageID can not be empty or equal to 0")
} }
if bsrq.Driver == "" { if bsrq.Driver == "" {
return errors.New("field Driver can not be empty") return errors.New("field Driver can not be empty")
} }
@ -58,16 +90,26 @@ func (bsrq GroupAddRequest) Validate() error {
return nil return nil
} }
// GroupAdd creates new Compute Group within BasicService.
// Compute Group is NOT started automatically,
// so you need to explicitly start it
func (b BService) GroupAdd(ctx context.Context, req GroupAddRequest) (uint64, error) { func (b BService) GroupAdd(ctx context.Context, req GroupAddRequest) (uint64, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return 0, err return 0, err
} }
url := "/cloudapi/bservice/groupAdd" url := "/cloudapi/bservice/groupAdd"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return strconv.ParseUint(string(res), 10, 64) result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
} }

@ -7,21 +7,28 @@ import (
"strconv" "strconv"
) )
// Request struct for remove group compute
type GroupComputeRemoveRequest struct { type GroupComputeRemoveRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute GROUP
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
ComputeID uint64 `url:"computeId"`
// ID of the Compute
// Required: true
ComputeID uint64 `url:"computeId"`
} }
func (bsrq GroupComputeRemoveRequest) Validate() error { func (bsrq GroupComputeRemoveRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
if bsrq.ComputeID == 0 { if bsrq.ComputeID == 0 {
return errors.New("field ComputeID can not be empty or equal to 0") return errors.New("field ComputeID can not be empty or equal to 0")
} }
@ -29,16 +36,24 @@ func (bsrq GroupComputeRemoveRequest) Validate() error {
return nil return nil
} }
// GroupComputeRemove makes group compute remove of the Basic Service
func (b BService) GroupComputeRemove(ctx context.Context, req GroupComputeRemoveRequest) (bool, error) { func (b BService) GroupComputeRemove(ctx context.Context, req GroupComputeRemoveRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupComputeRemove" url := "/cloudapi/bservice/groupComputeRemove"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,16 +7,21 @@ import (
"net/http" "net/http"
) )
// Request struct for get detailed information about Compute Group
type GroupGetRequest struct { type GroupGetRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
} }
func (bsrq GroupGetRequest) Validate() error { func (bsrq GroupGetRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -24,21 +29,26 @@ func (bsrq GroupGetRequest) Validate() error {
return nil return nil
} }
func (b BService) GroupGet(ctx context.Context, req GroupGetRequest) (*Group, error) { // GroupGet gets detailed specifications for the Compute Group
if err := req.Validate(); err != nil { func (b BService) GroupGet(ctx context.Context, req GroupGetRequest) (*RecordGroup, error) {
err := req.validate()
if err != nil {
return nil, err return nil, err
} }
url := "/cloudapi/bservice/groupGet" url := "/cloudapi/bservice/groupGet"
groupRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
group := &Group{} info := RecordGroup{}
if err := json.Unmarshal(groupRaw, group); err != nil {
err = json.Unmarshal(res, &info)
if err != nil {
return nil, err return nil, err
} }
return group, nil return &info, nil
} }

@ -7,21 +7,29 @@ import (
"strconv" "strconv"
) )
// Request struct for add parent Compute Group relation emove parent Compute Group
// relation to the specified Compute Group
type GroupParentAddRequest struct { type GroupParentAddRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
ParentID uint64 `url:"parentId"`
// ID of the parent Compute Group to register with the current Compute Group
// Required: true
ParentID uint64 `url:"parentId"`
} }
func (bsrq GroupParentAddRequest) Validate() error { func (bsrq GroupParentAddRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
if bsrq.ParentID == 0 { if bsrq.ParentID == 0 {
return errors.New("field ParentID can not be empty or equal to 0") return errors.New("field ParentID can not be empty or equal to 0")
} }
@ -29,16 +37,24 @@ func (bsrq GroupParentAddRequest) Validate() error {
return nil return nil
} }
// GroupParentAdd add parent Compute Group relation to the specified Compute Group
func (b BService) GroupParentAdd(ctx context.Context, req GroupParentAddRequest) (bool, error) { func (b BService) GroupParentAdd(ctx context.Context, req GroupParentAddRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupParentAdd" url := "/cloudapi/bservice/groupParentAdd"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,21 +7,30 @@ import (
"strconv" "strconv"
) )
// Request struct for remove parent Compute Group
// relation to the specified Compute Group
type GroupParentRemoveRequest struct { type GroupParentRemoveRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
ParentID uint64 `url:"parentId"`
// ID of the parent Compute Group
// to remove from the current Compute Group
// Required: true
ParentID uint64 `url:"parentId"`
} }
func (bsrq GroupParentRemoveRequest) Validate() error { func (bsrq GroupParentRemoveRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
if bsrq.ParentID == 0 { if bsrq.ParentID == 0 {
return errors.New("field ParentID can not be empty or equal to 0") return errors.New("field ParentID can not be empty or equal to 0")
} }
@ -29,16 +38,24 @@ func (bsrq GroupParentRemoveRequest) Validate() error {
return nil return nil
} }
// GroupParentRemove removes parent Compute Group relation to the specified Compute Group
func (b BService) GroupParentRemove(ctx context.Context, req GroupParentRemoveRequest) (bool, error) { func (b BService) GroupParentRemove(ctx context.Context, req GroupParentRemoveRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupParentRemove" url := "/cloudapi/bservice/groupParentRemove"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for destroy the specified Compute Group
type GroupRemoveRequest struct { type GroupRemoveRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
} }
func (bsrq GroupRemoveRequest) Validate() error { func (bsrq GroupRemoveRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -24,17 +29,25 @@ func (bsrq GroupRemoveRequest) Validate() error {
return nil return nil
} }
// GroupRemove destroy the specified Compute Group
func (b BService) GroupRemove(ctx context.Context, req GroupRemoveRequest) (bool, error) { func (b BService) GroupRemove(ctx context.Context, req GroupRemoveRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupRemove" url := "/cloudapi/bservice/groupRemove"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -9,43 +9,64 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for resize the group
type GroupResizeRequest struct { type GroupResizeRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group to resize
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
Count int64 `url:"count"`
Mode string `url:"mode"` // Either delta or absolute value of computes
// Required: true
Count int64 `url:"count"`
// Either delta or absolute value of computes
// Should be one of:
// - ABSOLUTE
// - RELATIVE
// Required: true
Mode string `url:"mode"`
} }
func (bsrq GroupResizeRequest) Validate() error { func (bsrq GroupResizeRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
if bsrq.Mode == "RELATIVE" && bsrq.Count == 0 { if bsrq.Mode == "RELATIVE" && bsrq.Count == 0 {
return errors.New("field Count can not be equal to 0 if Mode if 'RELATIVE'") return errors.New("field Count can not be equal to 0 if Mode if 'RELATIVE'")
} }
validate := validators.StringInSlice(bsrq.Mode, []string{"RELATIVE", "ABSOLUTE"})
if !validators.StringInSlice(bsrq.Mode, []string{"RELATIVE", "ABSOLUTE"}) { if !validate {
return errors.New("field Mode can only be one of 'RELATIVE' or 'ABSOLUTE'") return errors.New("field Mode can only be one of 'RELATIVE' or 'ABSOLUTE'")
} }
return nil return nil
} }
// GroupResize resize the group by changing the number of computes
func (b BService) GroupResize(ctx context.Context, req GroupResizeRequest) (uint64, error) { func (b BService) GroupResize(ctx context.Context, req GroupResizeRequest) (uint64, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return 0, err return 0, err
} }
url := "/cloudapi/bservice/groupResize" url := "/cloudapi/bservice/groupResize"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return strconv.ParseUint(string(res), 10, 64) result, err := strconv.ParseUint(string(res), 10, 64)
if err != nil {
return 0, err
}
return result, nil
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for start the specified Compute Group
type GroupStartRequest struct { type GroupStartRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group to start
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
} }
func (bsrq GroupStartRequest) Validate() error { func (bsrq GroupStartRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -24,16 +29,24 @@ func (bsrq GroupStartRequest) Validate() error {
return nil return nil
} }
// GroupStart starts the specified Compute Group within BasicService
func (b BService) GroupStart(ctx context.Context, req GroupStartRequest) (bool, error) { func (b BService) GroupStart(ctx context.Context, req GroupStartRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupStart" url := "/cloudapi/bservice/groupStart"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,17 +7,25 @@ import (
"strconv" "strconv"
) )
// Request struct for stop the specified Compute Group
type GroupStopRequest struct { type GroupStopRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group to stop
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
Force bool `url:"force,omitempty"`
// Force stop Compute Group
// Required: true
Force bool `url:"force,omitempty"`
} }
func (bsrq GroupStopRequest) Validate() error { func (bsrq GroupStopRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -25,16 +33,24 @@ func (bsrq GroupStopRequest) Validate() error {
return nil return nil
} }
// GroupStop stops the specified Compute Group within BasicService
func (b BService) GroupStop(ctx context.Context, req GroupStopRequest) (bool, error) { func (b BService) GroupStop(ctx context.Context, req GroupStopRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupStop" url := "/cloudapi/bservice/groupStop"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,22 +7,45 @@ import (
"strconv" "strconv"
) )
// Request struct for update existing Compute group
type GroupUpdateRequest struct { type GroupUpdateRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
// Required: true
ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"` CompGroupID uint64 `url:"compgroupId"`
Name string `url:"name,omitempty"`
Role string `url:"role,omitempty"` // Specify non-empty string to update Compute Group name
CPU uint64 `url:"cpu,omitempty"` // Required: false
RAM uint64 `url:"ram,omitempty"` Name string `url:"name,omitempty"`
Disk uint64 `url:"disk,omitempty"`
Force bool `url:"force,omitempty"` // Specify non-empty string to update group role
// Required: false
Role string `url:"role,omitempty"`
// Specify positive value to set new compute CPU count
// Required: false
CPU uint64 `url:"cpu,omitempty"`
// Specify positive value to set new compute RAM volume in MB
// Required: false
RAM uint64 `url:"ram,omitempty"`
// Specify new compute boot disk size in GB
// Required: false
Disk uint64 `url:"disk,omitempty"`
// Force resize Compute Group
// Required: false
Force bool `url:"force,omitempty"`
} }
func (bsrq GroupUpdateRequest) Validate() error { func (bsrq GroupUpdateRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -30,16 +53,24 @@ func (bsrq GroupUpdateRequest) Validate() error {
return nil return nil
} }
// GroupUpdate updates existing Compute group within Basic Service and apply new settings to its computes as necessary
func (b BService) GroupUpdate(ctx context.Context, req GroupUpdateRequest) (bool, error) { func (b BService) GroupUpdate(ctx context.Context, req GroupUpdateRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupUpdate" url := "/cloudapi/bservice/groupUpdate"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,17 +7,25 @@ import (
"strconv" "strconv"
) )
// Request struct for update External Network settings
type GroupUpdateExtNetRequest struct { type GroupUpdateExtNetRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
CompGroupID uint64 `url:"compgroupId"` // Required: true
ExtNets []uint64 `url:"extnets,omitempty"` ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"`
// List of Extnets to connect computes
// Required: false
ExtNets []uint64 `url:"extnets,omitempty"`
} }
func (bsrq GroupUpdateExtNetRequest) Validate() error { func (bsrq GroupUpdateExtNetRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -25,16 +33,24 @@ func (bsrq GroupUpdateExtNetRequest) Validate() error {
return nil return nil
} }
// GroupUpdateExtNet updates External Network settings for the group according to the new list
func (b BService) GroupUpdateExtNet(ctx context.Context, req GroupUpdateExtNetRequest) (bool, error) { func (b BService) GroupUpdateExtNet(ctx context.Context, req GroupUpdateExtNetRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupUpdateExtnet" url := "/cloudapi/bservice/groupUpdateExtnet"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,17 +7,25 @@ import (
"strconv" "strconv"
) )
// Request struct for update VINS settings
type GroupUpdateVINSRequest struct { type GroupUpdateVINSRequest struct {
ServiceID uint64 `url:"serviceId"` // ID of the Basic Service of Compute Group
CompGroupID uint64 `url:"compgroupId"` // Required: true
VINSes []uint64 `url:"vinses,omitempty"` ServiceID uint64 `url:"serviceId"`
// ID of the Compute Group
// Required: true
CompGroupID uint64 `url:"compgroupId"`
// List of ViNSes to connect computes
// Required: false
VINSes []uint64 `url:"vinses,omitempty"`
} }
func (bsrq GroupUpdateVINSRequest) Validate() error { func (bsrq GroupUpdateVINSRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.CompGroupID == 0 { if bsrq.CompGroupID == 0 {
return errors.New("field CompGroupID can not be empty or equal to 0") return errors.New("field CompGroupID can not be empty or equal to 0")
} }
@ -25,16 +33,24 @@ func (bsrq GroupUpdateVINSRequest) Validate() error {
return nil return nil
} }
// GroupUpdateVINS update ViNS settings for the group according to the new list
func (b BService) GroupUpdateVINS(ctx context.Context, req GroupUpdateVINSRequest) (bool, error) { func (b BService) GroupUpdateVINS(ctx context.Context, req GroupUpdateVINSRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/groupUpdateVins" url := "/cloudapi/bservice/groupUpdateVins"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -6,39 +6,59 @@ import (
"net/http" "net/http"
) )
// Request struct for get list/deleted list BasicService instances
type ListRequest struct { type ListRequest struct {
// ID of the account to query for BasicService instances
// Required: false
AccountID uint64 `url:"accountId,omitempty"` AccountID uint64 `url:"accountId,omitempty"`
RGID uint64 `url:"rgId,omitempty"`
Page uint64 `url:"page,omitempty"` // ID of the resource group to query for BasicService instances
Size uint64 `url:"size,omitempty"` // Required: false
RGID uint64 `url:"rgId,omitempty"`
// Page number
// Required: false
Page uint64 `url:"page,omitempty"`
// Page size
// Required: false
Size uint64 `url:"size,omitempty"`
} }
func (b BService) List(ctx context.Context, req ListRequest) (BasicServiceList, error) { // List gets list BasicService instances associated with the specified Resource Group
func (b BService) List(ctx context.Context, req ListRequest) (ListBasicServices, error) {
url := "/cloudapi/bservice/list" url := "/cloudapi/bservice/list"
bsListRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bsList := BasicServiceList{} list := ListBasicServices{}
if err := json.Unmarshal(bsListRaw, &bsList); err != nil {
err = json.Unmarshal(res, &list)
if err != nil {
return nil, err return nil, err
} }
return bsList, nil return list, nil
} }
func (b BService) ListDeleted(ctx context.Context, req ListRequest) (BasicServiceList, error) { // ListDeleted gets list deleted BasicService instances associated with the specified Resource Group
func (b BService) ListDeleted(ctx context.Context, req ListRequest) (ListBasicServices, error) {
url := "/cloudapi/bservice/listDeleted" url := "/cloudapi/bservice/listDeleted"
bsListRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
bsList := BasicServiceList{} list := ListBasicServices{}
if err := json.Unmarshal(bsListRaw, &bsList); err != nil {
err = json.Unmarshal(res, &list)
if err != nil {
return nil, err return nil, err
} }
return bsList, nil return list, nil
} }

@ -1,123 +1,334 @@
package bservice package bservice
type BasicService struct { // Detailed info about BasicService
AccountID uint64 `json:"accountId"` type RecordBasicService struct {
AccountName string `json:"accountName"` // Account ID
BaseDomain string `json:"baseDomain"` AccountID uint64 `json:"accountId"`
Computes []Compute `json:"computes"`
CPUTotal uint64 `json:"cpuTotal"` // Account name
CreatedBy string `json:"createdBy"` AccountName string `json:"accountName"`
CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"` // Base domain
DeletedTime uint64 `json:"deletedTime"` BaseDomain string `json:"baseDomain"`
DiskTotal uint64 `json:"diskTotal"`
GID uint64 `json:"gid"` // List Computes
Groups []uint64 `json:"groups"` Computes ListComputes `json:"computes"`
GroupsName []string `json:"groupsName"`
GUID uint64 `json:"guid"` // Number of cores
ID uint64 `json:"id"` CPUTotal uint64 `json:"cpuTotal"`
Milestones uint64 `json:"milestones"`
Name string `json:"name"` // Created by
ParentSrvID uint64 `json:"parentSrvId"` CreatedBy string `json:"createdBy"`
ParentSrvType string `json:"parentSrvType"`
RAMTotal uint64 `json:"ramTotal"` // Created time
RGID uint64 `json:"rgId"` CreatedTime uint64 `json:"createdTime"`
RGName string `json:"rgName"`
Snapshots []Snapshot `json:"snapshots"` // Deleted by
SSHKey string `json:"sshKey"` DeletedBy string `json:"deletedBy"`
SSHUser string `json:"sshUser"`
Status string `json:"status"` // Deleted time
TechStatus string `json:"techStatus"` DeletedTime uint64 `json:"deletedTime"`
UpdatedBy string `json:"updatedBy"`
UpdatedTime uint64 `json:"updatedTime"` // Amount of disk space used, GB
UserManaged bool `json:"userManaged"` DiskTotal uint64 `json:"diskTotal"`
// Grid ID
GID uint64 `json:"gid"`
// List of Service Compute Group IDs
Groups []uint64 `json:"groups"`
// List of compute groups by name
GroupsName []string `json:"groupsName"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Parent service ID
ParentSrvID uint64 `json:"parentSrvId"`
// Parent service type
ParentSrvType string `json:"parentSrvType"`
// Total amount of RAM, MB
RAMTotal uint64 `json:"ramTotal"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// List of snapshots
Snapshots ListSnapshots `json:"snapshots"`
// SSH key for connection
SSHKey string `json:"sshKey"`
// Username for SSH connection
SSHUser string `json:"sshUser"`
// status
Status string `json:"status"`
// TechStatus
TechStatus string `json:"techStatus"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// Whether user controlled
UserManaged bool `json:"userManaged"`
} }
type Compute struct { // Main information about Compute
CompGroupID uint64 `json:"compgroupId"` type ItemCompute struct {
// Compute group ID
CompGroupID uint64 `json:"compgroupId"`
// Compute group name
CompGroupName string `json:"compgroupName"` CompGroupName string `json:"compgroupName"`
// compute group role
CompGroupRole string `json:"compgroupRole"` CompGroupRole string `json:"compgroupRole"`
ID uint64 `json:"id"`
Name string `json:"name"` // ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
} }
type Snapshot struct { // List of Computes
GUID string `json:"guid"` type ListComputes []ItemCompute
Label string `json:"label"`
// Main information about Snapshot
type ItemSnapshot struct {
// GUID
GUID string `json:"guid"`
// Label
Label string `json:"label"`
// Timestamp
Timestamp uint64 `json:"timestamp"` Timestamp uint64 `json:"timestamp"`
Valid bool `json:"valid"`
// Valid or not
Valid bool `json:"valid"`
} }
type Group struct { // List of Snapshots
AccountID uint64 `json:"accountId"` type ListSnapshots []ItemSnapshot
AccountName string `json:"accountName"`
Computes []GroupCompute `json:"computes"` // Main information about Group
Consistency bool `json:"consistency"` type RecordGroup struct {
CPU uint64 `json:"cpu"` // Account ID
CreatedBy string `json:"createdBy"` AccountID uint64 `json:"accountId"`
CreatedTime uint64 `json:"createdTime"`
DeletedBy string `json:"deletedBy"` // Account Name
DeletedTime uint64 `json:"deletedTime"` AccountName string `json:"accountName"`
Disk uint64 `json:"disk"`
Driver string `json:"driver"` // List of Computes
ExtNets []uint64 `json:"extnets"` Computes ListGroupComputes `json:"computes"`
GID uint64 `json:"gid"`
GUID uint64 `json:"guid"` // Consistency or not
ID uint64 `json:"id"` Consistency bool `json:"consistency"`
ImageID uint64 `json:"imageId"`
Milestones uint64 `json:"milestones"` // Number of CPU
Name string `json:"name"` CPU uint64 `json:"cpu"`
Parents []uint64 `json:"parents"`
RAM uint64 `json:"ram"` // Created by
RGID uint64 `json:"rgId"` CreatedBy string `json:"createdBy"`
RGName string `json:"rgName"`
Role string `json:"role"` // Created time
SepID uint64 `json:"sepId"` CreatedTime uint64 `json:"createdTime"`
SeqNo uint64 `json:"seqNo"`
ServiceID uint64 `json:"serviceId"` // Deleted by
Status string `json:"status"` DeletedBy string `json:"deletedBy"`
TechStatus string `json:"techStatus"`
TimeoutStart uint64 `json:"timeoutStart"` // Deleted time
UpdatedBy string `json:"updatedBy"` DeletedTime uint64 `json:"deletedTime"`
UpdatedTime uint64 `json:"updatedTime"`
VINSes []uint64 `json:"vinses"` // Amount of disk
Disk uint64 `json:"disk"`
// Driver
Driver string `json:"driver"`
// list of External Network IDs
ExtNets []uint64 `json:"extnets"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// List of Parent IDs
Parents []uint64 `json:"parents"`
// Number of RAM, MB
RAM uint64 `json:"ram"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// Role
Role string `json:"role"`
// SEPID
SEPID uint64 `json:"sepId"`
// Sequence number
SeqNo uint64 `json:"seqNo"`
// Service ID
ServiceID uint64 `json:"serviceId"`
// Status
Status string `json:"status"`
// TechStatus
TechStatus string `json:"techStatus"`
// Timeout Start
TimeoutStart uint64 `json:"timeoutStart"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// List of VINS IDs
VINSes []uint64 `json:"vinses"`
} }
type GroupCompute struct { // Main information about Group Compute
ID uint64 `json:"id"` type ItemGroupCompute struct {
// ID
ID uint64 `json:"id"`
// IP Addresses
IPAddresses []string `json:"ipAddresses"` IPAddresses []string `json:"ipAddresses"`
Name string `json:"name"`
OSUsers []OSUser `json:"osUsers"` // Name
Name string `json:"name"`
// List of information about OS Users
OSUsers ListOSUsers `json:"osUsers"`
} }
type OSUser struct { // List of Group Computes
Login string `json:"login"` type ListGroupComputes []ItemGroupCompute
// Main information about OS User
type ItemOSUser struct {
// Login
Login string `json:"login"`
// Password
Password string `json:"password"` Password string `json:"password"`
} }
type BasicServiceShort struct { // List of information about OS Users
AccountID uint64 `json:"accountId"` type ListOSUsers []ItemOSUser
AccountName string `json:"accountName"`
BaseDomain string `json:"baseDomain"` // Main information about BasicService
CreatedBy string `json:"createdBy"` type ItemBasicService struct {
CreatedTime uint64 `json:"createdTime"` // Account ID
DeletedBy string `json:"deletedBy"` AccountID uint64 `json:"accountId"`
DeletedTime uint64 `json:"deletedTime"`
GID uint64 `json:"gid"` // Account name
Groups []uint64 `json:"groups"` AccountName string `json:"accountName"`
GUID uint64 `json:"guid"`
ID uint64 `json:"id"` // Base domain
Name string `json:"name"` BaseDomain string `json:"baseDomain"`
ParentSrvID uint64 `json:"parentSrvId"`
ParentSrvType string `json:"parentSrvType"` // Created by
RGID uint64 `json:"rgId"` CreatedBy string `json:"createdBy"`
RGName string `json:"rgName"`
SSHUser string `json:"sshUser"` // Created time
Status string `json:"status"` CreatedTime uint64 `json:"createdTime"`
TechStatus string `json:"techStatus"`
UpdatedBy string `json:"updatedBy"` // Deleted by
UpdatedTime uint64 `json:"updatedTime"` DeletedBy string `json:"deletedBy"`
UserManaged bool `json:"userManaged"`
// Deleted time
DeletedTime uint64 `json:"deletedTime"`
// Grid ID
GID uint64 `json:"gid"`
// List of group IDs
Groups []uint64 `json:"groups"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Name
Name string `json:"name"`
// Parent service ID
ParentSrvID uint64 `json:"parentSrvId"`
// Parent service type
ParentSrvType string `json:"parentSrvType"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Resource group name
RGName string `json:"rgName"`
// SSH user
SSHUser string `json:"sshUser"`
// Status
Status string `json:"status"`
// TechStatus
TechStatus string `json:"techStatus"`
// Updated by
UpdatedBy string `json:"updatedBy"`
// Updated time
UpdatedTime uint64 `json:"updatedTime"`
// User Managed or not
UserManaged bool `json:"userManaged"`
} }
type BasicServiceList []BasicServiceShort // List of BasicServices
type ListBasicServices []ItemBasicService

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for restores BasicService instance
type RestoreRequest struct { type RestoreRequest struct {
// ID of the BasicService to be restored
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq RestoreRequest) Validate() error { func (bsrq RestoreRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,16 +22,24 @@ func (bsrq RestoreRequest) Validate() error {
return nil return nil
} }
// Restore restores BasicService instance
func (b BService) Restore(ctx context.Context, req RestoreRequest) (bool, error) { func (b BService) Restore(ctx context.Context, req RestoreRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/restore" url := "/cloudapi/bservice/restore"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for create snapshot
type SnapshotCreateRequest struct { type SnapshotCreateRequest struct {
// ID of the Basic Service
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
Label string `url:"label"`
// Label of the snapshot
// Required: true
Label string `url:"label"`
} }
func (bsrq SnapshotCreateRequest) Validate() error { func (bsrq SnapshotCreateRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.Label == "" { if bsrq.Label == "" {
return errors.New("field Label can not be empty") return errors.New("field Label can not be empty")
} }
@ -24,16 +29,24 @@ func (bsrq SnapshotCreateRequest) Validate() error {
return nil return nil
} }
// SnapshotCreate create snapshot of the Basic Service
func (b BService) SnapshotCreate(ctx context.Context, req SnapshotCreateRequest) (bool, error) { func (b BService) SnapshotCreate(ctx context.Context, req SnapshotCreateRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/snapshotCreate" url := "/cloudapi/bservice/snapshotCreate"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for delete snapshot
type SnapshotDeleteRequest struct { type SnapshotDeleteRequest struct {
// ID of the Basic Service
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
Label string `url:"label"`
// Label of the snapshot
// Required: true
Label string `url:"label"`
} }
func (bsrq SnapshotDeleteRequest) Validate() error { func (bsrq SnapshotDeleteRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.Label == "" { if bsrq.Label == "" {
return errors.New("field Label can not be empty") return errors.New("field Label can not be empty")
} }
@ -24,16 +29,24 @@ func (bsrq SnapshotDeleteRequest) Validate() error {
return nil return nil
} }
// SnapshotDelete delete snapshot of the Basic Service
func (b BService) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) { func (b BService) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/snapshotDelete" url := "/cloudapi/bservice/snapshotDelete"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get list existing snapshots
type SnapshotListRequest struct { type SnapshotListRequest struct {
// ID of the Basic Service
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq SnapshotListRequest) Validate() error { func (bsrq SnapshotListRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,21 +22,26 @@ func (bsrq SnapshotListRequest) Validate() error {
return nil return nil
} }
func (b BService) SnapshotList(ctx context.Context, req SnapshotListRequest) ([]Snapshot, error) { // SnapshotList gets list existing snapshots of the Basic Service
if err := req.Validate(); err != nil { func (b BService) SnapshotList(ctx context.Context, req SnapshotListRequest) (ListSnapshots, error) {
err := req.validate()
if err != nil {
return nil, err return nil, err
} }
url := "/cloudapi/bservice/snapshotList" url := "/cloudapi/bservice/snapshotList"
snapshotListRaw, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
snapshotList := []Snapshot{} list := ListSnapshots{}
if err := json.Unmarshal(snapshotListRaw, &snapshotList); err != nil {
err = json.Unmarshal(res, &list)
if err != nil {
return nil, err return nil, err
} }
return snapshotList, nil return list, nil
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for rollback snapshot
type SnapshotRollbackRequest struct { type SnapshotRollbackRequest struct {
// ID of the Basic Service
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
Label string `url:"label"`
// Label of the snapshot
// Required: true
Label string `url:"label"`
} }
func (bsrq SnapshotRollbackRequest) Validate() error { func (bsrq SnapshotRollbackRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
if bsrq.Label == "" { if bsrq.Label == "" {
return errors.New("field Label can not be empty") return errors.New("field Label can not be empty")
} }
@ -24,16 +29,24 @@ func (bsrq SnapshotRollbackRequest) Validate() error {
return nil return nil
} }
// SnapshotRollback rollback snapshot of the Basic Service
func (b BService) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) { func (b BService) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/snapshotRollback" url := "/cloudapi/bservice/snapshotRollback"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for start service
type StartRequest struct { type StartRequest struct {
// ID of the service to start
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq StartRequest) Validate() error { func (bsrq StartRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,16 +22,26 @@ func (bsrq StartRequest) Validate() error {
return nil return nil
} }
// Start starts service.
// Starting a service technically means starting computes from all
// service groups according to group relations
func (b BService) Start(ctx context.Context, req StartRequest) (bool, error) { func (b BService) Start(ctx context.Context, req StartRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/start" url := "/cloudapi/bservice/start"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for stop service
type StopRequest struct { type StopRequest struct {
// ID of the service to stop
// Required: true
ServiceID uint64 `url:"serviceId"` ServiceID uint64 `url:"serviceId"`
} }
func (bsrq StopRequest) Validate() error { func (bsrq StopRequest) validate() error {
if bsrq.ServiceID == 0 { if bsrq.ServiceID == 0 {
return errors.New("field ServiceID can not be empty or equal to 0") return errors.New("field ServiceID can not be empty or equal to 0")
} }
@ -19,16 +22,26 @@ func (bsrq StopRequest) Validate() error {
return nil return nil
} }
// Stop stops service.
// Stopping a service technically means stopping computes from
// all service groups
func (b BService) Stop(ctx context.Context, req StopRequest) (bool, error) { func (b BService) Stop(ctx context.Context, req StopRequest) (bool, error) {
if err := req.Validate(); err != nil { err := req.validate()
if err != nil {
return false, err return false, err
} }
url := "/cloudapi/bservice/stop" url := "/cloudapi/bservice/stop"
res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := b.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return false, err return false, err
} }
return strconv.ParseBool(string(res)) result, err := strconv.ParseBool(string(res))
if err != nil {
return false, err
}
return result, nil
} }

@ -1,15 +1,18 @@
// List of method groups for the user
package cloudapi package cloudapi
import ( import (
"github.com/rudecs/decort-sdk/interfaces" "github.com/rudecs/decort-sdk/interfaces"
) )
type CloudApi struct { // Structure for creating request to CloudAPI groups
type CloudAPI struct {
client interfaces.Caller client interfaces.Caller
} }
func New(client interfaces.Caller) *CloudApi { // Builder to get access to CloudAPI
return &CloudApi{ func New(client interfaces.Caller) *CloudAPI {
return &CloudAPI{
client: client, client: client,
} }
} }

@ -4,6 +4,7 @@ import (
"github.com/rudecs/decort-sdk/pkg/cloudapi/compute" "github.com/rudecs/decort-sdk/pkg/cloudapi/compute"
) )
func (ca *CloudApi) Compute() *compute.Compute { // Accessing the Compute method group
func (ca *CloudAPI) Compute() *compute.Compute {
return compute.New(ca.client) return compute.New(ca.client)
} }

@ -6,12 +6,18 @@ import (
"net/http" "net/http"
) )
// Request struct for check all computes with current affinity label can start
type AffinityGroupCheckStartRequest struct { type AffinityGroupCheckStartRequest struct {
RGID uint64 `url:"rgId"` // ID of the resource group
// Required: true
RGID uint64 `url:"rgId"`
// Affinity group label
// Required: true
AffinityLabel string `url:"affinityLabel"` AffinityLabel string `url:"affinityLabel"`
} }
func (crq AffinityGroupCheckStartRequest) Validate() error { func (crq AffinityGroupCheckStartRequest) validate() error {
if crq.RGID == 0 { if crq.RGID == 0 {
return errors.New("validation-error: field RGID can not be empty or equal to 0") return errors.New("validation-error: field RGID can not be empty or equal to 0")
} }
@ -22,8 +28,9 @@ func (crq AffinityGroupCheckStartRequest) Validate() error {
return nil return nil
} }
// AffinityGroupCheckStart check all computes with current affinity label can start
func (c Compute) AffinityGroupCheckStart(ctx context.Context, req AffinityGroupCheckStartRequest) (string, error) { func (c Compute) AffinityGroupCheckStart(ctx context.Context, req AffinityGroupCheckStartRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for clear affinity label for compute
type AffinityLabelRemoveRequest struct { type AffinityLabelRemoveRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq AffinityLabelRemoveRequest) Validate() error { func (crq AffinityLabelRemoveRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq AffinityLabelRemoveRequest) Validate() error {
return nil return nil
} }
// AffinityLabelRemove clear affinity label for compute
func (c Compute) AffinityLabelRemove(ctx context.Context, req AffinityLabelRemoveRequest) (bool, error) { func (c Compute) AffinityLabelRemove(ctx context.Context, req AffinityLabelRemoveRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,12 +7,18 @@ import (
"strconv" "strconv"
) )
// Request struct for set affinity label for compute
type AffinityLabelSetRequest struct { type AffinityLabelSetRequest struct {
ComputeID uint64 `url:"computeId"` // ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"`
// Affinity group label
// Required: true
AffinityLabel string `url:"affinityLabel"` AffinityLabel string `url:"affinityLabel"`
} }
func (crq AffinityLabelSetRequest) Validate() error { func (crq AffinityLabelSetRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -23,8 +29,9 @@ func (crq AffinityLabelSetRequest) Validate() error {
return nil return nil
} }
// AffinityLabelSet set affinity label for compute
func (c Compute) AffinityLabelSet(ctx context.Context, req AffinityLabelSetRequest) (bool, error) { func (c Compute) AffinityLabelSet(ctx context.Context, req AffinityLabelSetRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,12 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get dict of computes
type AffinityRelationsRequest struct { type AffinityRelationsRequest struct {
ComputeID uint64 `url:"computeId"` // ID of the compute instance
AffinityLabel string `url:"affinityLabel"` // Required: true
ComputeID uint64 `url:"computeId"`
} }
func (crq AffinityRelationsRequest) Validate() error { func (crq AffinityRelationsRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -20,8 +22,9 @@ func (crq AffinityRelationsRequest) Validate() error {
return nil return nil
} }
func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsRequest) (*AffinityRelations, error) { // AffinityRelations gets dict of computes divided by affinity and anti affinity rules
err := req.Validate() func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsRequest) (*RecordAffinityRelations, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -33,12 +36,12 @@ func (c Compute) AffinityRelations(ctx context.Context, req AffinityRelationsReq
return nil, err return nil, err
} }
relations := &AffinityRelations{} info := RecordAffinityRelations{}
err = json.Unmarshal(res, relations) err = json.Unmarshal(res, &info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return relations, nil return &info, nil
} }

@ -9,50 +9,68 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for add affinity rule
type AffinityRuleAddRequest struct { type AffinityRuleAddRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
Topology string `url:"topology"`
Policy string `url:"policy"` // Compute or node, for whom rule applies
Mode string `url:"mode"` // Required: true
Key string `url:"key"` Topology string `url:"topology"`
Value string `url:"value"`
// The degree of 'strictness' of this rule
// Should be one of:
// - RECOMMENDED
// - REQUIRED
// Required: true
Policy string `url:"policy"`
// The comparison mode is 'value', recorded by the specified 'key'
// Should be one of:
// - EQ
// - EN
// - ANY
// Required: true
Mode string `url:"mode"`
// Key that are taken into account when analyzing this rule will be identified
// Required: true
Key string `url:"key"`
// Value that must match the key to be taken into account when analyzing this rule
// Required: true
Value string `url:"value"`
} }
func (crq AffinityRuleAddRequest) Validate() error { func (crq AffinityRuleAddRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Topology == "" { if crq.Topology == "" {
return errors.New("validation-error: field Topology can not be empty") return errors.New("validation-error: field Topology can not be empty")
} }
validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"})
if !validator { if !validator {
return errors.New("validation-error: field Topology can be only compute or node") return errors.New("validation-error: field Topology can be only compute or node")
} }
if crq.Policy == "" { if crq.Policy == "" {
return errors.New("validation-error: field Policy can not be empty") return errors.New("validation-error: field Policy can not be empty")
} }
validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"})
if !validator { if !validator {
return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED")
} }
if crq.Mode == "" { if crq.Mode == "" {
return errors.New("validation-error: field Mode can not be empty") return errors.New("validation-error: field Mode can not be empty")
} }
validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"})
if !validator { if !validator {
return errors.New("validation-error: field Mode can be only EQ, NE or ANY") return errors.New("validation-error: field Mode can be only EQ, NE or ANY")
} }
if crq.Key == "" { if crq.Key == "" {
return errors.New("validation-error: field Key can not be empty") return errors.New("validation-error: field Key can not be empty")
} }
if crq.Value == "" { if crq.Value == "" {
return errors.New("validation-error: field Value can not be empty") return errors.New("validation-error: field Value can not be empty")
} }
@ -60,8 +78,9 @@ func (crq AffinityRuleAddRequest) Validate() error {
return nil return nil
} }
// AffinityRuleAdd add affinity rule
func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (bool, error) { func (c Compute) AffinityRuleAdd(ctx context.Context, req AffinityRuleAddRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -9,50 +9,68 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for remove affinity rule
type AffinityRuleRemoveRequest struct { type AffinityRuleRemoveRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
Topology string `url:"topology"`
Policy string `url:"policy"` // Compute or node, for whom rule applies
Mode string `url:"mode"` // Required: true
Key string `url:"key"` Topology string `url:"topology"`
Value string `url:"value"`
// The degree of 'strictness' of this rule
// Should be one of:
// - RECOMMENDED
// - REQUIRED
// Required: true
Policy string `url:"policy"`
// The comparison mode is 'value', recorded by the specified 'key'
// Should be one of:
// - EQ
// - EN
// - ANY
// Required: true
Mode string `url:"mode"`
// Key that are taken into account when analyzing this rule will be identified
// Required: true
Key string `url:"key"`
// Value that must match the key to be taken into account when analyzing this rule
// Required: true
Value string `url:"value"`
} }
func (crq AffinityRuleRemoveRequest) Validate() error { func (crq AffinityRuleRemoveRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Topology == "" { if crq.Topology == "" {
return errors.New("validation-error: field Topology can not be empty") return errors.New("validation-error: field Topology can not be empty")
} }
validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"})
if !validator { if !validator {
return errors.New("validation-error: field Topology can be only compute or node") return errors.New("validation-error: field Topology can be only compute or node")
} }
if crq.Policy == "" { if crq.Policy == "" {
return errors.New("validation-error: field Policy can not be empty") return errors.New("validation-error: field Policy can not be empty")
} }
validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"})
if !validator { if !validator {
return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED")
} }
if crq.Mode == "" { if crq.Mode == "" {
return errors.New("validation-error: field Mode can not be empty") return errors.New("validation-error: field Mode can not be empty")
} }
validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"})
if !validator { if !validator {
return errors.New("validation-error: field Mode can be only EQ, NE or ANY") return errors.New("validation-error: field Mode can be only EQ, NE or ANY")
} }
if crq.Key == "" { if crq.Key == "" {
return errors.New("validation-error: field Key can not be empty") return errors.New("validation-error: field Key can not be empty")
} }
if crq.Value == "" { if crq.Value == "" {
return errors.New("validation-error: field Value can not be empty") return errors.New("validation-error: field Value can not be empty")
} }
@ -60,8 +78,9 @@ func (crq AffinityRuleRemoveRequest) Validate() error {
return nil return nil
} }
// AffinityRuleRemove remove affinity rule
func (c Compute) AffinityRuleRemove(ctx context.Context, req AffinityRuleRemoveRequest) (bool, error) { func (c Compute) AffinityRuleRemove(ctx context.Context, req AffinityRuleRemoveRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for clear affinity rules
type AffinityRulesClearRequest struct { type AffinityRulesClearRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq AffinityRulesClearRequest) Validate() error { func (crq AffinityRulesClearRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq AffinityRulesClearRequest) Validate() error {
return nil return nil
} }
// AffinityRulesClear clear affinity rules
func (c Compute) AffinityRulesClear(ctx context.Context, req AffinityRulesClearRequest) (bool, error) { func (c Compute) AffinityRulesClear(ctx context.Context, req AffinityRulesClearRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -9,50 +9,68 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for add anti affinity rule
type AntiAffinityRuleAddRequest struct { type AntiAffinityRuleAddRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
Topology string `url:"topology"`
Policy string `url:"policy"` // Compute or node, for whom rule applies
Mode string `url:"mode"` // Required: true
Key string `url:"key"` Topology string `url:"topology"`
Value string `url:"value"`
// The degree of 'strictness' of this rule
// Should be one of:
// - RECOMMENDED
// - REQUIRED
// Required: true
Policy string `url:"policy"`
// The comparison mode is 'value', recorded by the specified 'key'
// Should be one of:
// - EQ
// - EN
// - ANY
// Required: true
Mode string `url:"mode"`
// Key that are taken into account when analyzing this rule will be identified
// Required: true
Key string `url:"key"`
// Value that must match the key to be taken into account when analyzing this rule
// Required: true
Value string `url:"value"`
} }
func (crq AntiAffinityRuleAddRequest) Validate() error { func (crq AntiAffinityRuleAddRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Topology == "" { if crq.Topology == "" {
return errors.New("validation-error: field Topology can not be empty") return errors.New("validation-error: field Topology can not be empty")
} }
validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"})
if !validator { if !validator {
return errors.New("validation-error: field Topology can be only compute or node") return errors.New("validation-error: field Topology can be only compute or node")
} }
if crq.Policy == "" { if crq.Policy == "" {
return errors.New("validation-error: field Policy can not be empty") return errors.New("validation-error: field Policy can not be empty")
} }
validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"})
if !validator { if !validator {
return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED")
} }
if crq.Mode == "" { if crq.Mode == "" {
return errors.New("validation-error: field Mode can not be empty") return errors.New("validation-error: field Mode can not be empty")
} }
validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"})
if !validator { if !validator {
return errors.New("validation-error: field Mode can be only EQ, NE or ANY") return errors.New("validation-error: field Mode can be only EQ, NE or ANY")
} }
if crq.Key == "" { if crq.Key == "" {
return errors.New("validation-error: field Key can not be empty") return errors.New("validation-error: field Key can not be empty")
} }
if crq.Value == "" { if crq.Value == "" {
return errors.New("validation-error: field Value can not be empty") return errors.New("validation-error: field Value can not be empty")
} }
@ -60,8 +78,9 @@ func (crq AntiAffinityRuleAddRequest) Validate() error {
return nil return nil
} }
// AntiAffinityRuleAdd add anti affinity rule
func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (bool, error) { func (c Compute) AntiAffinityRuleAdd(ctx context.Context, req AntiAffinityRuleAddRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -9,50 +9,68 @@ import (
"github.com/rudecs/decort-sdk/internal/validators" "github.com/rudecs/decort-sdk/internal/validators"
) )
// Request struct for remove anti affinity rule
type AntiAffinityRuleRemoveRequest struct { type AntiAffinityRuleRemoveRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
Topology string `url:"topology"`
Policy string `url:"policy"` // Compute or node, for whom rule applies
Mode string `url:"mode"` // Required: true
Key string `url:"key"` Topology string `url:"topology"`
Value string `url:"value"`
// The degree of 'strictness' of this rule
// Should be one of:
// - RECOMMENDED
// - REQUIRED
// Required: true
Policy string `url:"policy"`
// The comparison mode is 'value', recorded by the specified 'key'
// Should be one of:
// - EQ
// - EN
// - ANY
// Required: true
Mode string `url:"mode"`
// Key that are taken into account when analyzing this rule will be identified
// Required: true
Key string `url:"key"`
// Value that must match the key to be taken into account when analyzing this rule
// Required: true
Value string `url:"value"`
} }
func (crq AntiAffinityRuleRemoveRequest) Validate() error { func (crq AntiAffinityRuleRemoveRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Topology == "" { if crq.Topology == "" {
return errors.New("validation-error: field Topology can not be empty") return errors.New("validation-error: field Topology can not be empty")
} }
validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"}) validator := validators.StringInSlice(crq.Topology, []string{"compute", "node"})
if !validator { if !validator {
return errors.New("validation-error: field Topology can be only compute or node") return errors.New("validation-error: field Topology can be only compute or node")
} }
if crq.Policy == "" { if crq.Policy == "" {
return errors.New("validation-error: field Policy can not be empty") return errors.New("validation-error: field Policy can not be empty")
} }
validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"}) validator = validators.StringInSlice(crq.Policy, []string{"RECOMMENDED", "REQUIRED"})
if !validator { if !validator {
return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED") return errors.New("validation-error: field Policy can be only RECOMMENDED or REQUIRED")
} }
if crq.Mode == "" { if crq.Mode == "" {
return errors.New("validation-error: field Mode can not be empty") return errors.New("validation-error: field Mode can not be empty")
} }
validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"}) validator = validators.StringInSlice(crq.Mode, []string{"EQ", "NE", "ANY"})
if !validator { if !validator {
return errors.New("validation-error: field Mode can be only EQ, NE or ANY") return errors.New("validation-error: field Mode can be only EQ, NE or ANY")
} }
if crq.Key == "" { if crq.Key == "" {
return errors.New("validation-error: field Key can not be empty") return errors.New("validation-error: field Key can not be empty")
} }
if crq.Value == "" { if crq.Value == "" {
return errors.New("validation-error: field Value can not be empty") return errors.New("validation-error: field Value can not be empty")
} }
@ -60,8 +78,9 @@ func (crq AntiAffinityRuleRemoveRequest) Validate() error {
return nil return nil
} }
// AntiAffinityRuleRemove remove anti affinity rule
func (c Compute) AntiAffinityRuleRemove(ctx context.Context, req AntiAffinityRuleRemoveRequest) (bool, error) { func (c Compute) AntiAffinityRuleRemove(ctx context.Context, req AntiAffinityRuleRemoveRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for clear anti affinity rules
type AntiAffinityRulesClearRequest struct { type AntiAffinityRulesClearRequest struct {
// ID of the compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq AntiAffinityRulesClearRequest) Validate() error { func (crq AntiAffinityRulesClearRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq AntiAffinityRulesClearRequest) Validate() error {
return nil return nil
} }
// AntiAffinityRulesClear clear anti affinity rules
func (c Compute) AntiAffinityRulesClear(ctx context.Context, req AntiAffinityRulesClearRequest) (bool, error) { func (c Compute) AntiAffinityRulesClear(ctx context.Context, req AntiAffinityRulesClearRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for attach GPU for compute
type AttachGPURequest struct { type AttachGPURequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
VGPUID uint64 `url:"vgpuId"`
// Identifier vGPU
// Required: true
VGPUID uint64 `url:"vgpuId"`
} }
func (crq AttachGPURequest) Validate() error { func (crq AttachGPURequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.VGPUID == 0 { if crq.VGPUID == 0 {
return errors.New("validation-error: field VGPUID can not be empty or equal to 0") return errors.New("validation-error: field VGPUID can not be empty or equal to 0")
} }
@ -24,8 +29,9 @@ func (crq AttachGPURequest) Validate() error {
return nil return nil
} }
// AttachGPU attach GPU for compute, returns vgpu id on success
func (c Compute) AttachGPU(ctx context.Context, req AttachGPURequest) (uint64, error) { func (c Compute) AttachGPU(ctx context.Context, req AttachGPURequest) (uint64, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return 0, err return 0, err
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
type AttachPciDeviceRequest struct { // Request struct for atttach PCI device
type AttachPCIDeviceRequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
DeviceID uint64 `url:"deviceId"`
// PCI device ID
// Required: true
DeviceID uint64 `url:"deviceId"`
} }
func (crq AttachPciDeviceRequest) Validate() error { func (crq AttachPCIDeviceRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DeviceID == 0 { if crq.DeviceID == 0 {
return errors.New("validation-error: field DeviceID can not be empty or equal to 0") return errors.New("validation-error: field DeviceID can not be empty or equal to 0")
} }
@ -24,8 +29,9 @@ func (crq AttachPciDeviceRequest) Validate() error {
return nil return nil
} }
func (c Compute) AttachPciDevice(ctx context.Context, req AttachPciDeviceRequest) (bool, error) { // AttachPCIDevice attach PCI device
err := req.Validate() func (c Compute) AttachPCIDevice(ctx context.Context, req AttachPCIDeviceRequest) (bool, error) {
err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get audit records
type AuditsRequest struct { type AuditsRequest struct {
// ID of the compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq AuditsRequest) Validate() error { func (crq AuditsRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("field ComputeID can not be empty or equal to 0") return errors.New("field ComputeID can not be empty or equal to 0")
} }
@ -19,21 +22,26 @@ func (crq AuditsRequest) Validate() error {
return nil return nil
} }
func (c Compute) Audits(ctx context.Context, req AuditsRequest) (AuditList, error) { // Audits gets audit records for the specified compute object
if err := req.Validate(); err != nil { func (c Compute) Audits(ctx context.Context, req AuditsRequest) (ListAudits, error) {
err := req.validate()
if err != nil {
return nil, err return nil, err
} }
url := "/cloudapi/compute/audits" url := "/cloudapi/compute/audits"
auditListRaw, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
if err != nil { if err != nil {
return nil, err return nil, err
} }
auditList := AuditList{} list := ListAudits{}
if err := json.Unmarshal(auditListRaw, &auditList); err != nil {
err = json.Unmarshal(res, &list)
if err != nil {
return nil, err return nil, err
} }
return auditList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for eject CD image
type CDEjectRequest struct { type CDEjectRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq CDEjectRequest) Validate() error { func (crq CDEjectRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq CDEjectRequest) Validate() error {
return nil return nil
} }
// CDEject eject CD image to compute's CD-ROM
func (c Compute) CDEject(ctx context.Context, req CDEjectRequest) (bool, error) { func (c Compute) CDEject(ctx context.Context, req CDEjectRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,12 +7,18 @@ import (
"strconv" "strconv"
) )
// Request struct for insert new CD image
type CDInsertRequest struct { type CDInsertRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
CDROMID uint64 `url:"cdromId"`
// ID of CD-ROM image
// Required: true
CDROMID uint64 `url:"cdromId"`
} }
func (crq CDInsertRequest) Validate() error { func (crq CDInsertRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -23,8 +29,9 @@ func (crq CDInsertRequest) Validate() error {
return nil return nil
} }
// CDInsert insert new CD image to compute's CD-ROM
func (c Compute) CDInsert(ctx context.Context, req CDInsertRequest) (bool, error) { func (c Compute) CDInsert(ctx context.Context, req CDInsertRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,14 +7,26 @@ import (
"strconv" "strconv"
) )
// Request struct for clone compute instance
type CloneRequest struct { type CloneRequest struct {
ComputeID uint64 `url:"computeId"` // ID of compute instance
Name string `url:"name"` // Required: true
ComputeID uint64 `url:"computeId"`
// Name of the clone
// Required: true
Name string `url:"name"`
// Timestamp of the parent's snapshot to create clone from
// Required: false
SnapshotTimestamp uint64 `url:"snapshotTimestamp"` SnapshotTimestamp uint64 `url:"snapshotTimestamp"`
SnapshotName string `url:"snapshotName"`
// Name of the parent's snapshot to create clone from
// Required: false
SnapshotName string `url:"snapshotName"`
} }
func (crq CloneRequest) Validate() error { func (crq CloneRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -25,8 +37,9 @@ func (crq CloneRequest) Validate() error {
return nil return nil
} }
// Clone clones compute instance
func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) { func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -42,5 +55,6 @@ func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
return result, nil return result, nil
} }

@ -1,13 +1,16 @@
// API Actor for managing Compute. This actor is a final API for endusers to manage Compute
package compute package compute
import ( import (
"github.com/rudecs/decort-sdk/interfaces" "github.com/rudecs/decort-sdk/interfaces"
) )
// Structure for creating request to compute
type Compute struct { type Compute struct {
client interfaces.Caller client interfaces.Caller
} }
// Builder for compute endpoints
func New(client interfaces.Caller) *Compute { func New(client interfaces.Caller) *Compute {
return &Compute{ return &Compute{
client, client,

@ -8,17 +8,27 @@ import (
"strings" "strings"
) )
// Request struct for create template
type CreateTemplateRequest struct { type CreateTemplateRequest struct {
// ID of the compute to create template from
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
Name string `url:"name"`
Async bool `url:"async"` // Name to assign to the template being created
// Required: true
Name string `url:"name"`
// Async API call
// For async call use CreateTemplateAsync
// For sync call use CreateTemplate
// Required: true
async bool `url:"async"`
} }
func (crq CreateTemplateRequest) Validate() error { func (crq CreateTemplateRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Name == "" { if crq.Name == "" {
return errors.New("validation-error: field Name can not be empty") return errors.New("validation-error: field Name can not be empty")
} }
@ -26,13 +36,14 @@ func (crq CreateTemplateRequest) Validate() error {
return nil return nil
} }
// CreateTemplate create template from compute instance
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (uint64, error) { func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (uint64, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return 0, err return 0, err
} }
req.Async = false req.async = false
url := "/cloudapi/compute/createTemplate" url := "/cloudapi/compute/createTemplate"
@ -49,13 +60,14 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest)
return result, nil return result, nil
} }
// CreateTemplateAsync create template from compute instance
func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) { func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }
req.Async = true req.async = true
url := "/cloudapi/compute/createTemplate" url := "/cloudapi/compute/createTemplate"

@ -7,13 +7,22 @@ import (
"strconv" "strconv"
) )
// Request struct for delete compute
type DeleteRequest struct { type DeleteRequest struct {
ComputeID uint64 `url:"computeId"` // ID of compute instance
Permanently bool `url:"permanently,omitempty"` // Required: true
DetachDisks bool `url:"detachDisks,omitempty"` ComputeID uint64 `url:"computeId"`
// Delete permanently
// Required: false
Permanently bool `url:"permanently,omitempty"`
// Set True if you want to detach data disks (if any) from the compute before its deletion
// Required: false
DetachDisks bool `url:"detachDisks,omitempty"`
} }
func (crq DeleteRequest) Validate() error { func (crq DeleteRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -21,8 +30,9 @@ func (crq DeleteRequest) Validate() error {
return nil return nil
} }
// Delete deletes compute
func (c Compute) Delete(ctx context.Context, req DeleteRequest) (bool, error) { func (c Compute) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }
@ -38,5 +48,6 @@ func (c Compute) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
return result, nil return result, nil
} }

@ -7,12 +7,18 @@ import (
"strconv" "strconv"
) )
// Request struct for detach vgpu for compute
type DetachGPURequest struct { type DetachGPURequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
VGPUID int64 `url:"vgpuId,omitempty"`
// Identifier virtual GPU
// Required: false
VGPUID int64 `url:"vgpuId,omitempty"`
} }
func (crq DetachGPURequest) Validate() error { func (crq DetachGPURequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -20,8 +26,10 @@ func (crq DetachGPURequest) Validate() error {
return nil return nil
} }
// DetachGPU detach vgpu for compute.
// If param vgpuid is equivalent -1, then detach all vgpu for compute
func (c Compute) DetachGPU(ctx context.Context, req DetachGPURequest) (bool, error) { func (c Compute) DetachGPU(ctx context.Context, req DetachGPURequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
type DetachPciDeviceRequest struct { // Request struct for detach PCI device
type DetachPCIDeviceRequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
DeviceID uint64 `url:"deviceId"`
// Pci device ID
// Required: true
DeviceID uint64 `url:"deviceId"`
} }
func (crq DetachPciDeviceRequest) Validate() error { func (crq DetachPCIDeviceRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DeviceID == 0 { if crq.DeviceID == 0 {
return errors.New("validation-error: field DeviceID can not be empty or equal to 0") return errors.New("validation-error: field DeviceID can not be empty or equal to 0")
} }
@ -24,8 +29,9 @@ func (crq DetachPciDeviceRequest) Validate() error {
return nil return nil
} }
func (c Compute) DetachPciDevice(ctx context.Context, req DetachPciDeviceRequest) (bool, error) { // DetachPCIDevice detach PCI device
err := req.Validate() func (c Compute) DetachPCIDevice(ctx context.Context, req DetachPCIDeviceRequest) (bool, error) {
err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for disable compute
type DisableRequest struct { type DisableRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq DisableRequest) Validate() error { func (crq DisableRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq DisableRequest) Validate() error {
return nil return nil
} }
// Disable disables compute
func (c Compute) Disable(ctx context.Context, req DisableRequest) (bool, error) { func (c Compute) Disable(ctx context.Context, req DisableRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,26 +7,53 @@ import (
"strconv" "strconv"
) )
// Request struct for create and attach disk to compute
type DiskAddRequest struct { type DiskAddRequest struct {
ComputeID uint64 `url:"computeId"` // ID of compute instance
DiskName string `url:"diskName"` // Required: true
Size uint64 `url:"size"` ComputeID uint64 `url:"computeId"`
DiskType string `url:"diskType,omitempty"`
SepID uint64 `url:"sepId,omitempty"` // Name for disk
Pool string `url:"pool,omitempty"` // Required: true
DiskName string `url:"diskName"`
// Disk size in GB
// Required: true
Size uint64 `url:"size"`
// Type of the disk
// Should be one of:
// - D
// - B
// Required: false
DiskType string `url:"diskType,omitempty"`
// Storage endpoint provider ID
// By default the same with boot disk
// Required: false
SepID uint64 `url:"sepId,omitempty"`
// Pool name
// By default will be chosen automatically
// Required: false
Pool string `url:"pool,omitempty"`
// Optional description
// Required: false
Description string `url:"desc,omitempty"` Description string `url:"desc,omitempty"`
ImageID uint64 `url:"imageId,omitempty"`
// Specify image id for create disk from template
// Required: false
ImageID uint64 `url:"imageId,omitempty"`
} }
func (crq DiskAddRequest) Validate() error { func (crq DiskAddRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Size == 0 { if crq.Size == 0 {
return errors.New("validation-error: field Size can not be empty or equal to 0") return errors.New("validation-error: field Size can not be empty or equal to 0")
} }
if crq.DiskName == "" { if crq.DiskName == "" {
return errors.New("validation-error: field DiskName can not be empty or equal to 0") return errors.New("validation-error: field DiskName can not be empty or equal to 0")
} }
@ -34,8 +61,9 @@ func (crq DiskAddRequest) Validate() error {
return nil return nil
} }
// DiskAdd creates new disk and attach to compute
func (c Compute) DiskAdd(ctx context.Context, req DiskAddRequest) (uint64, error) { func (c Compute) DiskAdd(ctx context.Context, req DiskAddRequest) (uint64, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return 0, err return 0, err
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for attach disk to compute
type DiskAttachRequest struct { type DiskAttachRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
DiskID uint64 `url:"diskId"`
// ID of the disk to attach
// Required: true
DiskID uint64 `url:"diskId"`
} }
func (crq DiskAttachRequest) Validate() error { func (crq DiskAttachRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DiskID == 0 { if crq.DiskID == 0 {
return errors.New("validation-error: field DiskID can not be empty or equal to 0") return errors.New("validation-error: field DiskID can not be empty or equal to 0")
} }
@ -24,8 +29,9 @@ func (crq DiskAttachRequest) Validate() error {
return nil return nil
} }
// DiskAttach attach disk to compute
func (c Compute) DiskAttach(ctx context.Context, req DiskAttachRequest) (bool, error) { func (c Compute) DiskAttach(ctx context.Context, req DiskAttachRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,17 +7,25 @@ import (
"strconv" "strconv"
) )
// Request struct for detach and delete disk from compute
type DiskDelRequest struct { type DiskDelRequest struct {
ComputeID uint64 `url:"computeId"` // ID of compute instance
DiskID uint64 `url:"diskId"` // Required: true
Permanently bool `url:"permanently"` ComputeID uint64 `url:"computeId"`
// ID of disk instance
// Required: true
DiskID uint64 `url:"diskId"`
// False if disk is to be deleted to recycle bin
// Required: true
Permanently bool `url:"permanently"`
} }
func (crq DiskDelRequest) Validate() error { func (crq DiskDelRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DiskID == 0 { if crq.DiskID == 0 {
return errors.New("validation-error: field DiskID can not be empty or equal to 0") return errors.New("validation-error: field DiskID can not be empty or equal to 0")
} }
@ -25,8 +33,9 @@ func (crq DiskDelRequest) Validate() error {
return nil return nil
} }
// DiskDel delete disk and detach from compute
func (c Compute) DiskDel(ctx context.Context, req DiskDelRequest) (bool, error) { func (c Compute) DiskDel(ctx context.Context, req DiskDelRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,16 +7,21 @@ import (
"strconv" "strconv"
) )
// Request struct for detach disk from compute
type DiskDetachRequest struct { type DiskDetachRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
DiskID uint64 `url:"diskId"`
// ID of the disk to detach
// Required: true
DiskID uint64 `url:"diskId"`
} }
func (crq DiskDetachRequest) Validate() error { func (crq DiskDetachRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DiskID == 0 { if crq.DiskID == 0 {
return errors.New("validation-error: field DiskID can not be empty or equal to 0") return errors.New("validation-error: field DiskID can not be empty or equal to 0")
} }
@ -24,8 +29,9 @@ func (crq DiskDetachRequest) Validate() error {
return nil return nil
} }
// DiskDetach detach disk from compute
func (c Compute) DiskDetach(ctx context.Context, req DiskDetachRequest) (bool, error) { func (c Compute) DiskDetach(ctx context.Context, req DiskDetachRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,21 +7,28 @@ import (
"strconv" "strconv"
) )
// Request struct for change QoS of the disk
type DiskQOSRequest struct { type DiskQOSRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
DiskID uint64 `url:"diskId"`
Limits string `url:"limits"` // ID of the disk to apply limits
// Required: true
DiskID uint64 `url:"diskId"`
// Limit IO for a certain disk total and read/write options are not allowed to be combined
// Required: true
Limits string `url:"limits"`
} }
func (crq DiskQOSRequest) Validate() error { func (crq DiskQOSRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DiskID == 0 { if crq.DiskID == 0 {
return errors.New("validation-error: field DiskID can not be empty or equal to 0") return errors.New("validation-error: field DiskID can not be empty or equal to 0")
} }
if crq.Limits == "" { if crq.Limits == "" {
return errors.New("validation-error: field Limits can not be empty") return errors.New("validation-error: field Limits can not be empty")
} }
@ -29,8 +36,9 @@ func (crq DiskQOSRequest) Validate() error {
return nil return nil
} }
// DiskQOS change QoS of the disk
func (c Compute) DiskQOS(ctx context.Context, req DiskQOSRequest) (bool, error) { func (c Compute) DiskQOS(ctx context.Context, req DiskQOSRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,21 +7,28 @@ import (
"strconv" "strconv"
) )
// Request struct for change disk size
type DiskResizeRequest struct { type DiskResizeRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
DiskID uint64 `url:"diskId"`
Size uint64 `url:"size"` // ID of the disk to resize
// Required: true
DiskID uint64 `url:"diskId"`
// New disk size
// Required: true
Size uint64 `url:"size"`
} }
func (crq DiskResizeRequest) Validate() error { func (crq DiskResizeRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.DiskID == 0 { if crq.DiskID == 0 {
return errors.New("validation-error: field DiskID can not be empty or equal to 0") return errors.New("validation-error: field DiskID can not be empty or equal to 0")
} }
if crq.Size == 0 { if crq.Size == 0 {
return errors.New("validation-error: field Size can not be empty or equal to 0") return errors.New("validation-error: field Size can not be empty or equal to 0")
} }
@ -29,8 +36,9 @@ func (crq DiskResizeRequest) Validate() error {
return nil return nil
} }
// DiskResize change disk size
func (c Compute) DiskResize(ctx context.Context, req DiskResizeRequest) (bool, error) { func (c Compute) DiskResize(ctx context.Context, req DiskResizeRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"strconv" "strconv"
) )
// Request struct for enable compute
type EnableRequest struct { type EnableRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq EnableRequest) Validate() error { func (crq EnableRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq EnableRequest) Validate() error {
return nil return nil
} }
// Enable enables compute
func (c Compute) Enable(ctx context.Context, req EnableRequest) (bool, error) { func (c Compute) Enable(ctx context.Context, req EnableRequest) (bool, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return false, err return false, err
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request for get information about compute
type GetRequest struct { type GetRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq GetRequest) Validate() error { func (crq GetRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq GetRequest) Validate() error {
return nil return nil
} }
func (c Compute) Get(ctx context.Context, req GetRequest) (*ComputeRecord, error) { // Get Gets information about compute
err := req.Validate() func (c Compute) Get(ctx context.Context, req GetRequest) (*RecordCompute, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,11 +36,12 @@ func (c Compute) Get(ctx context.Context, req GetRequest) (*ComputeRecord, error
return nil, err return nil, err
} }
compute := &ComputeRecord{} info := RecordCompute{}
err = json.Unmarshal(res, compute)
err = json.Unmarshal(res, &info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return compute, nil return &info, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get compute audits
type GetAuditsRequest struct { type GetAuditsRequest struct {
// ID of compute instance
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq GetAuditsRequest) Validate() error { func (crq GetAuditsRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq GetAuditsRequest) Validate() error {
return nil return nil
} }
func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (AuditShortList, error) { // GetAudits gets compute audits
err := req.Validate() func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (ListShortAudits, error) {
err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,11 +36,12 @@ func (c Compute) GetAudits(ctx context.Context, req GetAuditsRequest) (AuditShor
return nil, err return nil, err
} }
auditsList := AuditShortList{} list := ListShortAudits{}
err = json.Unmarshal(res, &auditsList)
err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return auditsList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"strings" "strings"
) )
// Request struct for get console URL
type GetConsoleURLRequest struct { type GetConsoleURLRequest struct {
// ID of compute instance to get console for
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq GetConsoleURLRequest) Validate() error { func (crq GetConsoleURLRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq GetConsoleURLRequest) Validate() error {
return nil return nil
} }
// GetConsoleURL gets computes console URL
func (c Compute) GetConsoleURL(ctx context.Context, req GetConsoleURLRequest) (string, error) { func (c Compute) GetConsoleURL(ctx context.Context, req GetConsoleURLRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }

@ -6,16 +6,21 @@ import (
"net/http" "net/http"
) )
// Request struct for get compute logs
type GetLogRequest struct { type GetLogRequest struct {
// ID of compute instance to get log for
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
Path string `url:"path"`
// Path to log file
// Required: true
Path string `url:"path"`
} }
func (crq GetLogRequest) Validate() error { func (crq GetLogRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
if crq.Path == "" { if crq.Path == "" {
return errors.New("validation-error: field Path can not be empty") return errors.New("validation-error: field Path can not be empty")
} }
@ -23,8 +28,9 @@ func (crq GetLogRequest) Validate() error {
return nil return nil
} }
// GetLog gets compute's log file by path
func (c Compute) GetLog(ctx context.Context, req GetLogRequest) (string, error) { func (c Compute) GetLog(ctx context.Context, req GetLogRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }
@ -39,16 +45,15 @@ func (c Compute) GetLog(ctx context.Context, req GetLogRequest) (string, error)
return string(res), nil return string(res), nil
} }
// GetLogGet gets compute's log file by path
func (c Compute) GetLogGet(ctx context.Context, req GetLogRequest) (string, error) { func (c Compute) GetLogGet(ctx context.Context, req GetLogRequest) (string, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return "", err return "", err
} }
url := "/compute/getLog" url := "/cloudapi//compute/getLog"
prefix := "/cloudapi"
url = prefix + url
res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req) res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
if err != nil { if err != nil {
return "", err return "", err

@ -6,14 +6,24 @@ import (
"net/http" "net/http"
) )
// Request struct for get list available computes
type ListRequest struct { type ListRequest struct {
IncludeDeleted bool `url:"includedeleted,omitempty"` // Include deleted computes
Page uint64 `url:"page,omitempty"` // Required: false
Size uint64 `url:"size,omitempty"` IncludeDeleted bool `url:"includedeleted,omitempty"`
}
// Page number
// Required: false
Page uint64 `url:"page,omitempty"`
func (c Compute) List(ctx context.Context, req ListRequest) (ComputeList, error) { // Page size
// Required: false
Size uint64 `url:"size,omitempty"`
}
// List gets list of the available computes.
// Filtering based on status is possible
func (c Compute) List(ctx context.Context, req ListRequest) (ListComputes, error) {
url := "/cloudapi/compute/list" url := "/cloudapi/compute/list"
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
@ -21,12 +31,12 @@ func (c Compute) List(ctx context.Context, req ListRequest) (ComputeList, error)
return nil, err return nil, err
} }
computeList := ComputeList{} list := ListComputes{}
err = json.Unmarshal(res, &computeList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return computeList, nil return list, nil
} }

@ -6,13 +6,19 @@ import (
"net/http" "net/http"
) )
// Request struct for get deleted computes list
type ListDeletedRequest struct { type ListDeletedRequest struct {
// Page number
// Required: false
Page uint64 `url:"page,omitempty"` Page uint64 `url:"page,omitempty"`
// Page size
// Required: false
Size uint64 `url:"size,omitempty"` Size uint64 `url:"size,omitempty"`
} }
func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (ComputeList, error) { // ListDeleted gets list all deleted computes
func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (ListComputes, error) {
url := "/cloudapi/compute/listDeleted" url := "/cloudapi/compute/listDeleted"
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req) res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
@ -20,12 +26,12 @@ func (c Compute) ListDeleted(ctx context.Context, req ListDeletedRequest) (Compu
return nil, err return nil, err
} }
computeList := ComputeList{} list := ListComputes{}
err = json.Unmarshal(res, &computeList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return computeList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get list PCI devices
type ListPCIDeviceRequest struct { type ListPCIDeviceRequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq ListPCIDeviceRequest) Validate() error { func (crq ListPCIDeviceRequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq ListPCIDeviceRequest) Validate() error {
return nil return nil
} }
// ListPCIDevice gets list PCI device
func (c Compute) ListPCIDevice(ctx context.Context, req ListPCIDeviceRequest) ([]interface{}, error) { func (c Compute) ListPCIDevice(ctx context.Context, req ListPCIDeviceRequest) ([]interface{}, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,12 +36,12 @@ func (c Compute) ListPCIDevice(ctx context.Context, req ListPCIDeviceRequest) ([
return nil, err return nil, err
} }
pciDeviceList := []interface{}{} list := []interface{}{}
err = json.Unmarshal(res, &pciDeviceList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return pciDeviceList, nil return list, nil
} }

@ -7,11 +7,14 @@ import (
"net/http" "net/http"
) )
// Request struct for get list vGPU
type ListVGPURequest struct { type ListVGPURequest struct {
// Identifier compute
// Required: true
ComputeID uint64 `url:"computeId"` ComputeID uint64 `url:"computeId"`
} }
func (crq ListVGPURequest) Validate() error { func (crq ListVGPURequest) validate() error {
if crq.ComputeID == 0 { if crq.ComputeID == 0 {
return errors.New("validation-error: field ComputeID can not be empty or equal to 0") return errors.New("validation-error: field ComputeID can not be empty or equal to 0")
} }
@ -19,8 +22,9 @@ func (crq ListVGPURequest) Validate() error {
return nil return nil
} }
// ListVGPU gets list vGPU
func (c Compute) ListVGPU(ctx context.Context, req ListVGPURequest) ([]interface{}, error) { func (c Compute) ListVGPU(ctx context.Context, req ListVGPURequest) ([]interface{}, error) {
err := req.Validate() err := req.validate()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -32,12 +36,12 @@ func (c Compute) ListVGPU(ctx context.Context, req ListVGPURequest) ([]interface
return nil, err return nil, err
} }
pciDeviceList := []interface{}{} list := []interface{}{}
err = json.Unmarshal(res, &pciDeviceList) err = json.Unmarshal(res, &list)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return pciDeviceList, nil return list, nil
} }

File diff suppressed because it is too large Load Diff

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

Loading…
Cancel
Save