Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29c7f143fe | |||
| 264538f492 | |||
| c06a3198f6 | |||
| c9e4ae6afe | |||
| 2a1593f45f | |||
| 190f24dac1 | |||
| 256dba5134 | |||
| b7137683ab | |||
| 10e3e19892 | |||
| aaf0857ff0 | |||
| 7d6cda7119 | |||
| 84b64b7d80 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
cmd/
|
cmd/
|
||||||
|
.idea/
|
||||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,12 +1,4 @@
|
|||||||
## Version 1.2.1
|
## Version 1.4.7
|
||||||
|
|
||||||
### Bug fixes
|
### Bugfix
|
||||||
|
- Deleted validate:"required" tag from IPCIDR field in cloudapi/vins/createInRg request struct
|
||||||
#### Legacy Client
|
|
||||||
|
|
||||||
- Fixed password and username encoding
|
|
||||||
- Fixed request params absence in HTTP Transport
|
|
||||||
|
|
||||||
#### All
|
|
||||||
|
|
||||||
- Updated module to new repository
|
|
||||||
202
README.md
202
README.md
@@ -7,6 +7,8 @@ Decort SDK - это библиотека, написанная на языке G
|
|||||||
- Версия 1.0.x Decort-SDK соответствует 3.8.4 версии платформы
|
- Версия 1.0.x Decort-SDK соответствует 3.8.4 версии платформы
|
||||||
- Версия 1.1.x Decort-SDK соответствует 3.8.5 версии платформы
|
- Версия 1.1.x Decort-SDK соответствует 3.8.5 версии платформы
|
||||||
- Версия 1.2.x Decort-SDK соответствует 3.8.5 версии платформы
|
- Версия 1.2.x Decort-SDK соответствует 3.8.5 версии платформы
|
||||||
|
- Версия 1.3.x Decort-SDK соответствует 3.8.5 версии платформы
|
||||||
|
- Версия 1.4.x Decort-SDK соответствует 3.8.6 версии платформы
|
||||||
|
|
||||||
## Оглавление
|
## Оглавление
|
||||||
|
|
||||||
@@ -16,6 +18,10 @@ Decort SDK - это библиотека, написанная на языке G
|
|||||||
- [Cloudbroker](#cloudbroker)
|
- [Cloudbroker](#cloudbroker)
|
||||||
- [Работа с библиотекой](#работа-с-библиотекой)
|
- [Работа с библиотекой](#работа-с-библиотекой)
|
||||||
- [Настройка конфигурации клиента](#настройка-конфигурации-клиента)
|
- [Настройка конфигурации клиента](#настройка-конфигурации-клиента)
|
||||||
|
- [Пример конфигурации клиента](#пример-конфигурации-клиента)
|
||||||
|
- [Парсинг конфигурации из файла](#парсинг-конфигурации-из-файла)
|
||||||
|
- [Пример JSON конфигурации](#пример-json-конфигурации)
|
||||||
|
- [Пример YAML конфигурации](#пример-yaml-конфигурации)
|
||||||
- [Создание клиента](#создание-клиента)
|
- [Создание клиента](#создание-клиента)
|
||||||
- [Создание структуры запроса](#cоздание-структуры-запроса)
|
- [Создание структуры запроса](#cоздание-структуры-запроса)
|
||||||
- [Выполнение запроса](#выполнение-запроса)
|
- [Выполнение запроса](#выполнение-запроса)
|
||||||
@@ -24,6 +30,10 @@ Decort SDK - это библиотека, написанная на языке G
|
|||||||
- [Сериализация](#сериализация)
|
- [Сериализация](#сериализация)
|
||||||
- [Работа с legacy клиентом](#работа-с-legacy-клиентом)
|
- [Работа с legacy клиентом](#работа-с-legacy-клиентом)
|
||||||
- [Настройка конфигурации legacy клиента](#настройка-конфигурации-legacy-клиента)
|
- [Настройка конфигурации legacy клиента](#настройка-конфигурации-legacy-клиента)
|
||||||
|
- [Пример конфигурации legacy клиента](#пример-конфигурации-legacy-клиента)
|
||||||
|
- [Парсинг legacy конфигурации из файла](#парсинг-legacy-конфигурации-из-файла)
|
||||||
|
- [Пример legacy JSON конфигурации](#пример-legacy-json-конфигурации)
|
||||||
|
- [Пример legacy YAML конфигурации](#пример-legacy-yaml-конфигурации)
|
||||||
- [Создание legacy клиента](#создание-legacy-клиента)
|
- [Создание legacy клиента](#создание-legacy-клиента)
|
||||||
- [Создание структуры запроса](#cоздание-структуры-запроса)
|
- [Создание структуры запроса](#cоздание-структуры-запроса)
|
||||||
- [Выполнение запроса](#выполнение-запроса)
|
- [Выполнение запроса](#выполнение-запроса)
|
||||||
@@ -93,9 +103,10 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
|
|||||||
Алгоритм работы с библиотекой выглядит следующим образом:
|
Алгоритм работы с библиотекой выглядит следующим образом:
|
||||||
|
|
||||||
1. Настройка конфигурации клиента.
|
1. Настройка конфигурации клиента.
|
||||||
2. Создание клиента.
|
2. Парсинг конфигурации из файла.
|
||||||
3. Создание структуры запроса.
|
3. Создание клиента.
|
||||||
4. Выполнение запроса.
|
4. Создание структуры запроса.
|
||||||
|
5. Выполнение запроса.
|
||||||
|
|
||||||
### Настройка конфигурации клиента
|
### Настройка конфигурации клиента
|
||||||
|
|
||||||
@@ -107,15 +118,17 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
|
|||||||
| SSOURL | string | Да | URL адрес сервиса аутентификации и авторизации |
|
| SSOURL | string | Да | URL адрес сервиса аутентификации и авторизации |
|
||||||
| DecortURL | string | Да | URL адрес платформы, с которой будет осуществляться взаимодействие |
|
| DecortURL | string | Да | URL адрес платформы, с которой будет осуществляться взаимодействие |
|
||||||
| Retries | uint | Нет | Кол-во неудачных попыток выполнения запроса, по умолчанию - 5 |
|
| Retries | uint | Нет | Кол-во неудачных попыток выполнения запроса, по умолчанию - 5 |
|
||||||
|
| Timeout | config.Duration | Нет | Таймаут HTTP клиента, по умолчанию - без ограничений |
|
||||||
| SSLSkipVerify | bool | Нет | Пропуск проверки подлинности сертификата, по умолчанию - true |
|
| SSLSkipVerify | bool | Нет | Пропуск проверки подлинности сертификата, по умолчанию - true |
|
||||||
| Token | string | Нет | JWT токен |
|
| Token | string | Нет | JWT токен |
|
||||||
|
|
||||||
Пример кода:
|
#### Пример конфигурации клиента
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main(){
|
func main(){
|
||||||
// Настройка конфигурации
|
// Настройка конфигурации
|
||||||
cfg := config.Config{
|
cfg := config.Config{
|
||||||
@@ -125,9 +138,54 @@ func main(){
|
|||||||
DecortURL: "https://mr4.digitalenergy.online",
|
DecortURL: "https://mr4.digitalenergy.online",
|
||||||
Retries: 5,
|
Retries: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg.SetTimeout(5 * time.Minute)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Парсинг конфигурации из файла
|
||||||
|
|
||||||
|
Также возможно создать переменную конфигурации из JSON или YAML файла, используя функцию `ParseConfigJSON` (или `ParseConfigYAML`) из пакета config.
|
||||||
|
<br>
|
||||||
|
*См. пример файлов конфигурации ниже и в директории `samples/`.*
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Парсинг конфигурации из JSON-файла
|
||||||
|
cfg := config.ParseConfigJSON("<PATH>")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Пример JSON конфигурации
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"appId": "<APP_ID>",
|
||||||
|
"appSecret": "<APP_SECRET>",
|
||||||
|
"ssoUrl": "https://sso.digitalenergy.online",
|
||||||
|
"decortUrl": "https://mr4.digitalenergy.online",
|
||||||
|
"retries": 5,
|
||||||
|
"timeout": "5m",
|
||||||
|
"sslSkipVerify": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Пример YAML конфигурации
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
appId: <APP_ID>
|
||||||
|
appSecret: <APP_SECRET>
|
||||||
|
ssoUrl: https://sso.digitalenergy.online
|
||||||
|
decortUrl: https://mr4.digitalenergy.online
|
||||||
|
retries: 5
|
||||||
|
timeout: 5m
|
||||||
|
sslSkipVerify: false
|
||||||
|
```
|
||||||
|
|
||||||
### Создание клиента
|
### Создание клиента
|
||||||
|
|
||||||
Создание клиента происходит с помощью функции-строителя `New` из основного пакета `decort-sdk`, для избежания проблем с именами, пакету можно присвоить алиас `decort`. Функция принимает конфигурацию, возвращает структуру `DecortClient`, с помощью которой можно взаимодействовать с платформой.
|
Создание клиента происходит с помощью функции-строителя `New` из основного пакета `decort-sdk`, для избежания проблем с именами, пакету можно присвоить алиас `decort`. Функция принимает конфигурацию, возвращает структуру `DecortClient`, с помощью которой можно взаимодействовать с платформой.
|
||||||
@@ -138,8 +196,8 @@ func main(){
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
decort "github.com/rudecs/decort-sdk"
|
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -152,6 +210,8 @@ func main() {
|
|||||||
Retries: 5,
|
Retries: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg.SetTimeout(5 * time.Minute)
|
||||||
|
|
||||||
// Создание клиента
|
// Создание клиента
|
||||||
client := decort.New(cfg)
|
client := decort.New(cfg)
|
||||||
}
|
}
|
||||||
@@ -302,9 +362,9 @@ type CreateRequest struct {
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
decort "github.com/rudecs/decort-sdk"
|
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmx86"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -402,9 +462,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
decort "github.com/rudecs/decort-sdk"
|
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmx86"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -484,6 +544,52 @@ filtered := resp.
|
|||||||
// ....
|
// ....
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Также у `compute`, `disks`, и `lb` присутствуют специфические функции фильтрации, отправляющие дополнительные запросы. В качестве параметров принимают:
|
||||||
|
- context.Context - контекст для доп. запроса
|
||||||
|
- id (или другое поле, по которому производится фильтрация)
|
||||||
|
- interfaces.Caller - DECORT-клиент для запроса
|
||||||
|
|
||||||
|
Так как эти функции возвращают не только результирующий слайс, но и возможную ошибку - конвейер придется прервать для обработки ошибки.
|
||||||
|
|
||||||
|
|
||||||
|
#### Использование на примере `compute.FilterByK8SID`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
// Чтение конфигурации из файла
|
||||||
|
cfg := config.ParseConfigJSON("<PATH>")
|
||||||
|
|
||||||
|
// Создание клиента
|
||||||
|
client := decort.New(cfg)
|
||||||
|
|
||||||
|
// Создание структуры запроса compute/list
|
||||||
|
req := compute.ListRequest{}
|
||||||
|
|
||||||
|
// Запрос
|
||||||
|
resp, err := client.CloudAPI().Compute().List(context.Background(), req)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Фильтрация по id кластера.
|
||||||
|
// Первый аргумент - контекст
|
||||||
|
// Второй - ID кластера
|
||||||
|
// Третий - DECORT-клиент
|
||||||
|
filtered, err := resp.FilterByK8SID(context.Background(), <k8sID>, client)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err) // Возможная ошибка запроса
|
||||||
|
}
|
||||||
|
|
||||||
|
// Доп. фильтрация и сортировка результата - worker ноды кластера
|
||||||
|
workers := filtered.FilterByK8SWorkers().SortByCreatedTime(false)
|
||||||
|
|
||||||
|
// Доп. фильтрация и сортировка результата - master ноды кластера
|
||||||
|
masters := filtered.FilterByK8SMasters().SortByCreatedTime(true)
|
||||||
|
|
||||||
|
// ....
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Сортировка
|
### Сортировка
|
||||||
|
|
||||||
Функции сортировки так же могут быть объединены в конвейер:
|
Функции сортировки так же могут быть объединены в конвейер:
|
||||||
@@ -536,9 +642,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
decort "github.com/rudecs/decort-sdk"
|
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
"github.com/rudecs/decort-sdk/pkg/cloudbroker/compute"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/compute"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -549,6 +655,8 @@ func main() {
|
|||||||
DecortURL: "<DECORT_URL>",
|
DecortURL: "<DECORT_URL>",
|
||||||
Retries: 5,
|
Retries: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg.SetTimeout(5 * time.Minute)
|
||||||
|
|
||||||
// Создание клиента
|
// Создание клиента
|
||||||
client := decort.New(cfg)
|
client := decort.New(cfg)
|
||||||
@@ -595,26 +703,69 @@ func main() {
|
|||||||
| Password | string | Да | пароль legacy пользователя |
|
| Password | string | Да | пароль legacy пользователя |
|
||||||
| DecortURL | string | Да | URL адрес платформы, с которой будет осуществляться взаимодействие |
|
| DecortURL | string | Да | URL адрес платформы, с которой будет осуществляться взаимодействие |
|
||||||
| Retries | uint | Нет | Кол-во неудачных попыток выполнения запроса, по умолчанию - 5 |
|
| Retries | uint | Нет | Кол-во неудачных попыток выполнения запроса, по умолчанию - 5 |
|
||||||
|
| Timeout | config.Duration | Нет | Таймаут HTTP клиента, по умолчанию - без ограничений |
|
||||||
| SSLSkipVerify | bool | Нет | Пропуск проверки подлинности сертификата, по умолчанию - true |
|
| SSLSkipVerify | bool | Нет | Пропуск проверки подлинности сертификата, по умолчанию - true |
|
||||||
| Token | string | Нет | JWT токен |
|
| Token | string | Нет | JWT токен |
|
||||||
|
|
||||||
Пример кода:
|
#### Пример конфигурации legacy клиента
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import (
|
import (
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main(){
|
func main(){
|
||||||
// Настройка конфигурации
|
// Настройка конфигурации
|
||||||
legacyCfg := config.LegacyConfig{
|
legacyCfg := config.LegacyConfig{
|
||||||
Username: "<USERNAME>",
|
Username: "<USERNAME>",
|
||||||
Password: "<PASSWORD>",
|
Password: "<PASSWORD>",
|
||||||
DecortURL: "https://mr4.digitalenergy.online",
|
DecortURL: "https://mr4.digitalenergy.online",
|
||||||
Retries: 5,
|
Retries: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
legacyCfg.SetTimeout(5 * time.Minute)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Парсинг legacy конфигурации из файла
|
||||||
|
|
||||||
|
Также возможно создать переменную конфигурации из JSON или YAML файла, используя функцию `ParseLegacyConfigJSON` (или `ParseLegacyConfigYAML`) из пакета config.
|
||||||
|
<br>
|
||||||
|
*См. пример файлов конфигурации ниже и в директории `samples/`.*
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Парсинг конфигурации из YAML-файла
|
||||||
|
legacyCfg := config.ParseLegacyConfigYAML("<PATH>")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Пример legacy JSON конфигурации
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "<USERNAME>",
|
||||||
|
"password": "<PASSWORD>",
|
||||||
|
"decortUrl": "https://mr4.digitalenergy.online",
|
||||||
|
"retries": 5,
|
||||||
|
"timeout": "5m",
|
||||||
|
"sslSkipVerify": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Пример legacy YAML конфигурации
|
||||||
|
```yaml
|
||||||
|
username: <USERNAME>
|
||||||
|
password: <PASSWORD>
|
||||||
|
decortUrl: https://mr4.digitalenergy.online
|
||||||
|
retries: 5
|
||||||
|
timeout: 5m
|
||||||
|
sslSkipVerify: true
|
||||||
|
```
|
||||||
### Создание legacy клиента
|
### Создание legacy клиента
|
||||||
|
|
||||||
Создание клиента происходит с помощью функции-строителя `NewLegacy` из основного пакета `decort-sdk`, для избежания проблем с именами, пакету можно присвоить алиас `decort`. Функция принимает конфигурацию, возвращает структуру `DecortClient`, с помощью которой можно взаимодействовать с платформой.
|
Создание клиента происходит с помощью функции-строителя `NewLegacy` из основного пакета `decort-sdk`, для избежания проблем с именами, пакету можно присвоить алиас `decort`. Функция принимает конфигурацию, возвращает структуру `DecortClient`, с помощью которой можно взаимодействовать с платформой.
|
||||||
@@ -625,8 +776,8 @@ func main(){
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
decort "github.com/rudecs/decort-sdk"
|
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -638,6 +789,8 @@ func main() {
|
|||||||
Retries: 5,
|
Retries: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
legacyCfg.SetTimeout(5 * time.Minute)
|
||||||
|
|
||||||
// Создание клиента
|
// Создание клиента
|
||||||
legacyClient := decort.NewLegacy(cfg)
|
legacyClient := decort.NewLegacy(cfg)
|
||||||
}
|
}
|
||||||
@@ -651,8 +804,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
decort "github.com/rudecs/decort-sdk"
|
decort "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -685,4 +838,3 @@ func main() {
|
|||||||
|
|
||||||
fmt.Println(res)
|
fmt.Println(res)
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Also the library have structures for responses.
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go get -u github.com/rudecs/decort-sdk
|
go get -u repository.basistech.ru/BASIS/decort-golang-sdk
|
||||||
```
|
```
|
||||||
|
|
||||||
## API List
|
## API List
|
||||||
@@ -29,8 +29,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/rudecs/decort-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
"github.com/rudecs/decort-sdk/pkg/cloudapi/kvmx86"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/kvmx86"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -1,39 +1,105 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
// Configuration for creating request to platform
|
// Configuration for creating request to platform
|
||||||
type Config struct {
|
type Config struct {
|
||||||
// JWT platform token
|
// JWT platform token
|
||||||
// Required: false
|
// Required: false
|
||||||
// Example: "qwqwdfwv68979we0q9bfv7e9sbvd89798qrwv97ff"
|
// Example: "qwqwdfwv68979we0q9bfv7e9sbvd89798qrwv97ff"
|
||||||
Token string
|
Token string `json:"token" yaml:"token"`
|
||||||
|
|
||||||
// Application (client) identifier for authorization
|
// Application (client) identifier for authorization
|
||||||
// in the cloud platform controller in oauth2 mode.
|
// in the cloud platform controller in oauth2 mode.
|
||||||
// Required: true
|
// Required: true
|
||||||
// Example: "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu"
|
// Example: "ewqfrvea7s890avw804389qwguf234h0otfi3w4eiu"
|
||||||
AppID string
|
AppID string `json:"appId" yaml:"appId" validate:"required"`
|
||||||
|
|
||||||
// Application (client) secret code for authorization
|
// Application (client) secret code for authorization
|
||||||
// in the cloud platform controller in oauth2 mode.
|
// in the cloud platform controller in oauth2 mode.
|
||||||
// Example: "frvet09rvesfis0c9erv9fsov0vsdfi09ovds0f"
|
// Example: "frvet09rvesfis0c9erv9fsov0vsdfi09ovds0f"
|
||||||
AppSecret string
|
AppSecret string `json:"appSecret" yaml:"appSecret" validate:"required"`
|
||||||
|
|
||||||
// Platform authentication service address
|
// Platform authentication service address
|
||||||
// Required: true
|
// Required: true
|
||||||
// Example: "https://sso.digitalenergy.online"
|
// Example: "https://sso.digitalenergy.online"
|
||||||
SSOURL string
|
SSOURL string `json:"ssoUrl" yaml:"ssoUrl" validate:"url"`
|
||||||
|
|
||||||
// The address of the platform on which the actions are planned
|
// The address of the platform on which the actions are planned
|
||||||
// Required: true
|
// Required: true
|
||||||
// Example: "https://mr4.digitalenergy.online"
|
// Example: "https://mr4.digitalenergy.online"
|
||||||
DecortURL string
|
DecortURL string `json:"decortUrl" yaml:"decortUrl" validate:"url"`
|
||||||
|
|
||||||
// Amount platform request attempts
|
// Amount platform request attempts
|
||||||
// Default value: 5
|
// Default value: 5
|
||||||
// Required: false
|
// Required: false
|
||||||
Retries uint64
|
Retries uint64 `json:"retries" yaml:"retries"`
|
||||||
|
|
||||||
// Skip verify, true by default
|
// Skip verify, true by default
|
||||||
// Required: false
|
// Required: false
|
||||||
SSLSkipVerify bool
|
SSLSkipVerify bool `json:"sslSkipVerify" yaml:"sslSkipVerify"`
|
||||||
|
|
||||||
|
// HTTP client timeout, unlimited if left empty
|
||||||
|
// Required: false
|
||||||
|
Timeout Duration `json:"timeout" yaml:"timeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTimeout is used to set HTTP client timeout.
|
||||||
|
func (c *Config) SetTimeout(dur time.Duration) {
|
||||||
|
c.Timeout = Duration(dur)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseConfigJSON parses Config from specified JSON-formatted file.
|
||||||
|
func ParseConfigJSON(path string) (Config, error) {
|
||||||
|
file, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
err = json.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validators.ValidateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return Config{}, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseConfigYAML parses Config from specified YAML-formatted file.
|
||||||
|
func ParseConfigYAML(path string) (Config, error) {
|
||||||
|
file, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
return Config{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validators.ValidateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return Config{}, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,99 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
// Legacy client configuration
|
// Legacy client configuration
|
||||||
type LegacyConfig struct {
|
type LegacyConfig struct {
|
||||||
// ServiceAccount username
|
// ServiceAccount username
|
||||||
// Required: true
|
// Required: true
|
||||||
// Example : "osh_mikoev"
|
// Example : "osh_mikoev"
|
||||||
Username string
|
Username string `json:"username" yaml:"username" validate:"required"`
|
||||||
|
|
||||||
// ServiceAccount password
|
// ServiceAccount password
|
||||||
// Required: true
|
// Required: true
|
||||||
// Example: "[1o>hYkjnJr)HI78q7t&#%8Lm"
|
// Example: "[1o>hYkjnJr)HI78q7t&#%8Lm"
|
||||||
Password string
|
Password string `json:"password" yaml:"password" validate:"required"`
|
||||||
|
|
||||||
// Platform token
|
// Platform token
|
||||||
// Required: false
|
// Required: false
|
||||||
// Example: "158e76424b0d4810b6086hgbhj928fc4a6bc06e"
|
// Example: "158e76424b0d4810b6086hgbhj928fc4a6bc06e"
|
||||||
Token string
|
Token string `json:"token" yaml:"token"`
|
||||||
|
|
||||||
// Address of the platform on which the actions are planned
|
// Address of the platform on which the actions are planned
|
||||||
// Required: true
|
// Required: true
|
||||||
// Example: "https://mr4.digitalenergy.online"
|
// Example: "https://mr4.digitalenergy.online"
|
||||||
DecortURL string
|
DecortURL string `json:"decortUrl" yaml:"decortUrl" validate:"url"`
|
||||||
|
|
||||||
// Amount platform request attempts
|
// Amount platform request attempts
|
||||||
// Default value: 5
|
// Default value: 5
|
||||||
// Required: false
|
// Required: false
|
||||||
Retries uint64
|
Retries uint64 `json:"retries" yaml:"retries"`
|
||||||
|
|
||||||
// Skip verify, true by default
|
// Skip verify, true by default
|
||||||
// Required: false
|
// Required: false
|
||||||
SSLSkipVerify bool
|
SSLSkipVerify bool `json:"sslSkipVerify" yaml:"sslSkipVerify"`
|
||||||
|
|
||||||
|
// HTTP client timeout, unlimited if left empty
|
||||||
|
// Required: false
|
||||||
|
Timeout Duration `json:"timeout" yaml:"timeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTimeout is used to set HTTP client timeout.
|
||||||
|
func (c *LegacyConfig) SetTimeout(dur time.Duration) {
|
||||||
|
c.Timeout = Duration(dur)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseLegacyConfigJSON parses LegacyConfig from specified JSON-formatted file.
|
||||||
|
func ParseLegacyConfigJSON(path string) (LegacyConfig, error) {
|
||||||
|
file, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return LegacyConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var config LegacyConfig
|
||||||
|
|
||||||
|
err = json.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
return LegacyConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validators.ValidateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return LegacyConfig{}, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseLegacyConfigYAML parses LegacyConfig from specified YAML-formatted file.
|
||||||
|
func ParseLegacyConfigYAML(path string) (LegacyConfig, error) {
|
||||||
|
file, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return LegacyConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var config LegacyConfig
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
return LegacyConfig{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validators.ValidateConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return LegacyConfig{}, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
50
config/timeouts.go
Normal file
50
config/timeouts.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Duration is a wrapper around time.Duration (used for better user experience)
|
||||||
|
type Duration time.Duration
|
||||||
|
|
||||||
|
func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var v interface{}
|
||||||
|
if err := unmarshal(&v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch value := v.(type) {
|
||||||
|
case string:
|
||||||
|
tmp, err := time.ParseDuration(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*d = Duration(tmp)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Invalid duration %v", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||||
|
var v interface{}
|
||||||
|
if err := json.Unmarshal(b, &v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch value := v.(type) {
|
||||||
|
case string:
|
||||||
|
tmp, err := time.ParseDuration(value)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*d = Duration(tmp)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("Invalid duration %v", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Duration) Get() time.Duration {
|
||||||
|
return time.Duration(*d)
|
||||||
|
}
|
||||||
2
go.mod
2
go.mod
@@ -5,11 +5,13 @@ go 1.20
|
|||||||
require (
|
require (
|
||||||
github.com/go-playground/validator/v10 v10.11.2
|
github.com/go-playground/validator/v10 v10.11.2
|
||||||
github.com/google/go-querystring v1.1.0
|
github.com/google/go-querystring v1.1.0
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
golang.org/x/crypto v0.5.0 // indirect
|
golang.org/x/crypto v0.5.0 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.4.0 // indirect
|
||||||
|
|||||||
7
go.sum
7
go.sum
@@ -1,3 +1,4 @@
|
|||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
@@ -11,10 +12,14 @@ github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
|||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
@@ -26,5 +31,7 @@ golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
|||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -35,6 +35,6 @@ func NewHttpClient(cfg config.Config) *http.Client {
|
|||||||
//TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
//TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
},
|
},
|
||||||
|
|
||||||
Timeout: 5 * time.Minute,
|
Timeout: cfg.Timeout.Get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
|
||||||
|
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
|
||||||
)
|
)
|
||||||
@@ -28,6 +27,6 @@ func NewLegacyHttpClient(cfg config.LegacyConfig) *http.Client {
|
|||||||
decortURL: cfg.DecortURL,
|
decortURL: cfg.DecortURL,
|
||||||
},
|
},
|
||||||
|
|
||||||
Timeout: 5 * time.Minute,
|
Timeout: cfg.Timeout.Get(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||||||
body := fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s&response_type=id_token", t.clientID, t.clientSecret)
|
body := fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s&response_type=id_token", t.clientID, t.clientSecret)
|
||||||
bodyReader := strings.NewReader(body)
|
bodyReader := strings.NewReader(body)
|
||||||
|
|
||||||
|
t.ssoURL = strings.TrimSuffix(t.ssoURL, "/")
|
||||||
|
|
||||||
req, _ := http.NewRequestWithContext(req.Context(), "POST", t.ssoURL+"/v1/oauth/access_token", bodyReader)
|
req, _ := http.NewRequestWithContext(req.Context(), "POST", t.ssoURL+"/v1/oauth/access_token", bodyReader)
|
||||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,47 @@
|
|||||||
package validators
|
package validators
|
||||||
|
|
||||||
import "github.com/go-playground/validator/v10"
|
import (
|
||||||
|
"github.com/go-playground/validator/v10"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// protoValidator is used to validate Proto fields.
|
||||||
|
func protoValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, protoValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// accessTypeValidator is used to validate AccessType fields.
|
||||||
|
func accessTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, accessTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resTypesValidator is used to validate ResTypes fields.
|
||||||
|
func resTypesValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldSlice, ok := fe.Field().Interface().([]string)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range fieldSlice {
|
||||||
|
if !StringInSlice(value, resTypesValues) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// driverValidator is used to validate Driver fields.
|
||||||
|
func driverValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, driverValues)
|
||||||
|
}
|
||||||
|
|
||||||
// accountCUTypeValidator is used to validate CUType field.
|
// accountCUTypeValidator is used to validate CUType field.
|
||||||
func accountCUTypeValidator(fe validator.FieldLevel) bool {
|
func accountCUTypeValidator(fe validator.FieldLevel) bool {
|
||||||
@@ -9,20 +50,6 @@ func accountCUTypeValidator(fe validator.FieldLevel) bool {
|
|||||||
return StringInSlice(fieldValue, accountCUTypeValues)
|
return StringInSlice(fieldValue, accountCUTypeValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// accountAccessTypeValidator is used to validate AccessType field.
|
|
||||||
func accountAccessTypeValidator(fe validator.FieldLevel) bool {
|
|
||||||
fieldValue := fe.Field().String()
|
|
||||||
|
|
||||||
return StringInSlice(fieldValue, accountAccessTypeValues)
|
|
||||||
}
|
|
||||||
|
|
||||||
// bserviceDriverValidator is used to validate Driver field.
|
|
||||||
func bserviceDriverValidator(fe validator.FieldLevel) bool {
|
|
||||||
fieldValue := fe.Field().String()
|
|
||||||
|
|
||||||
return StringInSlice(fieldValue, bserviceDriverValues)
|
|
||||||
}
|
|
||||||
|
|
||||||
// bserviceModeValidator is used to validate Mode field.
|
// bserviceModeValidator is used to validate Mode field.
|
||||||
func bserviceModeValidator(fe validator.FieldLevel) bool {
|
func bserviceModeValidator(fe validator.FieldLevel) bool {
|
||||||
fieldValue := fe.Field().String()
|
fieldValue := fe.Field().String()
|
||||||
@@ -65,11 +92,76 @@ func computeNetTypeValidator(fe validator.FieldLevel) bool {
|
|||||||
return StringInSlice(fieldValue, computeNetTypeValues)
|
return StringInSlice(fieldValue, computeNetTypeValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// computeProtoValidator is used to validate Proto field.
|
// computeOrderValidator is used to validate Order field.
|
||||||
func computeProtoValidator(fe validator.FieldLevel) bool {
|
func computeOrderValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldSlice, ok := fe.Field().Interface().([]string)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, value := range fieldSlice {
|
||||||
|
if !StringInSlice(value, computeOrderValues) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// computeDataDisksValidator is used to validate DataDisks field.
|
||||||
|
func computeDataDisksValidator(fe validator.FieldLevel) bool {
|
||||||
fieldValue := fe.Field().String()
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
return StringInSlice(fieldValue, computeProtoValues)
|
return StringInSlice(fieldValue, computeDataDisksValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// diskTypeValidator is used to validate Type field.
|
||||||
|
func diskTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, diskTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// flipgroupClientTypeValidator is used to validate ClientType field.
|
||||||
|
func flipgroupClientTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, flipgroupClientTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// kvmNetTypeValidator is used to validate NetType field.
|
||||||
|
func kvmNetTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, kvmNetTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// lbAlgorithmValidator is used to validate Algorithm field.
|
||||||
|
func lbAlgorithmValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, lbAlgorithmValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rgDefNetValidator is used to validate DefNet field.
|
||||||
|
func rgDefNetValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, rgDefNetValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rgNetTypeValidator is used to validate NetType field.
|
||||||
|
func rgNetTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, rgNetTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// vinsTypeValidator is used to validate Type field.
|
||||||
|
func vinsTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, vinsTypeValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// imageBootTypeValidator is used to validate BootType field.
|
// imageBootTypeValidator is used to validate BootType field.
|
||||||
@@ -108,3 +200,59 @@ func imageArchitectureValidator(fe validator.FieldLevel) bool {
|
|||||||
|
|
||||||
return StringInSlice(fieldValue, imageArchitectureValues)
|
return StringInSlice(fieldValue, imageArchitectureValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sepFieldTypeValidator is used to validate FieldType field.
|
||||||
|
func sepFieldTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, sepFieldTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hwPathValidator is used to validate HWPath field.
|
||||||
|
func hwPathValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
ok, _ := regexp.MatchString(`^\b[0-9a-f]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.\d{1}$`, fieldValue)
|
||||||
|
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// networkPluginValidator is used to validate NetworkPlugin field
|
||||||
|
func networkPluginValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
fieldValue = strings.ToLower(fieldValue)
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, networkPluginValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
// networkPluginsValidator is used to validate NetworkPlugins field
|
||||||
|
func networkPluginsValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldSlice, ok := fe.Field().Interface().([]string)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range fieldSlice {
|
||||||
|
item = strings.ToLower(item)
|
||||||
|
|
||||||
|
if !StringInSlice(item, networkPluginValues) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func interfaceStateValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
fieldValue = strings.ToLower(fieldValue)
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, interfaceStateValues)
|
||||||
|
}
|
||||||
|
|
||||||
|
func strictLooseValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
fieldValue = strings.ToLower(fieldValue)
|
||||||
|
|
||||||
|
return StringInSlice(fieldValue, strictLooseValues)
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ func ValidateRequest(req interface{}) error {
|
|||||||
return validate.Struct(req)
|
return validate.Struct(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateConfig(cfg interface{}) error {
|
||||||
|
validate := getDecortValidator()
|
||||||
|
return validate.Struct(cfg)
|
||||||
|
}
|
||||||
|
|
||||||
func ValidationError(fe validator.FieldError) error {
|
func ValidationError(fe validator.FieldError) error {
|
||||||
return errors.New(errorMessage(fe))
|
return errors.New(errorMessage(fe))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
|
|
||||||
switch fe.Tag() {
|
switch fe.Tag() {
|
||||||
|
|
||||||
// Default Validators
|
// Common Validators
|
||||||
case "required":
|
case "required":
|
||||||
return fmt.Sprintf("%s %s is required", prefix, fe.Field())
|
return fmt.Sprintf("%s %s is required", prefix, fe.Field())
|
||||||
case "gt":
|
case "gt":
|
||||||
@@ -26,13 +26,31 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
case "email":
|
case "email":
|
||||||
return fmt.Sprintf("%s %s: unexpected E-Mail format", prefix, fe.Field())
|
return fmt.Sprintf("%s %s: unexpected E-Mail format", prefix, fe.Field())
|
||||||
|
|
||||||
// Account Validators
|
case "driver":
|
||||||
case "accountAccessType":
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
return fmt.Sprintf("%s %s must be one of the followng: %s",
|
|
||||||
prefix,
|
prefix,
|
||||||
fe.Field(),
|
fe.Field(),
|
||||||
joinValues(accountAccessTypeValues))
|
joinValues(driverValues))
|
||||||
|
|
||||||
|
case "accessType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(accessTypeValues))
|
||||||
|
|
||||||
|
case "resTypes":
|
||||||
|
return fmt.Sprintf("%s %s can contain only the following values: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(resTypesValues))
|
||||||
|
|
||||||
|
case "proto":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(protoValues))
|
||||||
|
|
||||||
|
// Account Validators
|
||||||
case "accountCUType":
|
case "accountCUType":
|
||||||
return fmt.Sprintf("%s %s must be one of the following: %s",
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
prefix,
|
prefix,
|
||||||
@@ -40,12 +58,6 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
joinValues(accountCUTypeValues))
|
joinValues(accountCUTypeValues))
|
||||||
|
|
||||||
// BService Validators
|
// BService Validators
|
||||||
case "bserviceDriver":
|
|
||||||
return fmt.Sprintf("%s %s must be one of the following: %s",
|
|
||||||
prefix,
|
|
||||||
fe.Field(),
|
|
||||||
joinValues(bserviceDriverValues))
|
|
||||||
|
|
||||||
case "bserviceMode":
|
case "bserviceMode":
|
||||||
return fmt.Sprintf("%s %s must be one of the following: %s",
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
prefix,
|
prefix,
|
||||||
@@ -83,14 +95,68 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
fe.Field(),
|
fe.Field(),
|
||||||
joinValues(computeNetTypeValues))
|
joinValues(computeNetTypeValues))
|
||||||
|
|
||||||
case "computeProto":
|
case "computeOrder":
|
||||||
|
return fmt.Sprintf("%s %s can contain only the following values: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(computeOrderValues))
|
||||||
|
|
||||||
|
case "computeDataDisks":
|
||||||
return fmt.Sprintf("%s %s must be one of the following: %s",
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
prefix,
|
prefix,
|
||||||
fe.Field(),
|
fe.Field(),
|
||||||
joinValues(computeProtoValues))
|
joinValues(computeDataDisksValues))
|
||||||
|
|
||||||
|
// Disk Validators
|
||||||
|
case "diskType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(diskTypeValues))
|
||||||
|
|
||||||
|
// Flipgroup Validators
|
||||||
|
case "flipgroupClientType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(flipgroupClientTypeValues))
|
||||||
|
|
||||||
|
// KVM_X86/KVM_PPC Validators
|
||||||
|
case "kvmNetType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(kvmNetTypeValues))
|
||||||
|
|
||||||
|
// LB Validators
|
||||||
|
case "lbAlgorithm":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(lbAlgorithmValues))
|
||||||
|
|
||||||
|
// RG Validators
|
||||||
|
case "rgDefNet":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(rgDefNetValues))
|
||||||
|
|
||||||
|
case "rgNetType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(rgNetTypeValues))
|
||||||
|
|
||||||
|
// ViNS Validators
|
||||||
|
case "vinsType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(vinsTypeValues))
|
||||||
|
|
||||||
// Image Validators
|
// Image Validators
|
||||||
case "bootType":
|
case "imageBootType":
|
||||||
return fmt.Sprintf("%s %s must be one of the following: %s",
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
prefix,
|
prefix,
|
||||||
fe.Field(),
|
fe.Field(),
|
||||||
@@ -114,6 +180,43 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
fe.Field(),
|
fe.Field(),
|
||||||
joinValues(imageArchitectureValues))
|
joinValues(imageArchitectureValues))
|
||||||
|
|
||||||
|
// SEP Validators
|
||||||
|
case "sepFieldType":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(sepFieldTypeValues))
|
||||||
|
|
||||||
|
// HWPath Validators
|
||||||
|
case "hwPath":
|
||||||
|
return fmt.Sprintf("%s %s must be in format 0000:1f:2b.0",
|
||||||
|
prefix,
|
||||||
|
fe.Field())
|
||||||
|
|
||||||
|
// Network plugin Validators
|
||||||
|
case "networkPlugin":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(networkPluginValues))
|
||||||
|
|
||||||
|
case "networkPlugins":
|
||||||
|
return fmt.Sprintf("%s %s must contain only the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(networkPluginValues))
|
||||||
|
|
||||||
|
case "strict_loose":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(strictLooseValues))
|
||||||
|
|
||||||
|
case "interfaceState":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(interfaceStateValues))
|
||||||
}
|
}
|
||||||
|
|
||||||
return fe.Error()
|
return fe.Error()
|
||||||
|
|||||||
@@ -7,34 +7,45 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
once sync.Once
|
once sync.Once
|
||||||
instance *DecortValidator
|
decortValidator = validator.New()
|
||||||
)
|
)
|
||||||
|
|
||||||
type DecortValidator struct {
|
|
||||||
decortValidator *validator.Validate
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDecortValidator returns singleton instance of DecortValidator.
|
// getDecortValidator returns singleton instance of DecortValidator.
|
||||||
func getDecortValidator() *validator.Validate {
|
func getDecortValidator() *validator.Validate {
|
||||||
if instance == nil {
|
once.Do(func() {
|
||||||
once.Do(func() {
|
err := registerAllValidators(decortValidator)
|
||||||
instance = new(DecortValidator)
|
if err != nil {
|
||||||
instance.decortValidator = validator.New()
|
panic(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
err := registerAllValidators(instance.decortValidator)
|
return decortValidator
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance.decortValidator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerAllValidators registers all custom validators in DecortValidator.
|
// registerAllValidators registers all custom validators in DecortValidator.
|
||||||
func registerAllValidators(validate *validator.Validate) error {
|
func registerAllValidators(validate *validator.Validate) error {
|
||||||
err := validate.RegisterValidation("bootType", imageBootTypeValidator)
|
err := validate.RegisterValidation("proto", protoValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("accessType", accessTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("resTypes", resTypesValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("driver", driverValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("imageBootType", imageBootTypeValidator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -54,21 +65,11 @@ func registerAllValidators(validate *validator.Validate) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = validate.RegisterValidation("accountAccessType", accountAccessTypeValidator)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = validate.RegisterValidation("accountCUType", accountCUTypeValidator)
|
err = validate.RegisterValidation("accountCUType", accountCUTypeValidator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = validate.RegisterValidation("bserviceDriver", bserviceDriverValidator)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = validate.RegisterValidation("bserviceMode", bserviceModeValidator)
|
err = validate.RegisterValidation("bserviceMode", bserviceModeValidator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -99,7 +100,77 @@ func registerAllValidators(validate *validator.Validate) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = validate.RegisterValidation("computeProto", computeProtoValidator)
|
err = validate.RegisterValidation("computeOrder", computeOrderValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("computeDataDisks", computeDataDisksValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("diskType", diskTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("flipgroupClientType", flipgroupClientTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("kvmNetType", kvmNetTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("lbAlgorithm", lbAlgorithmValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("rgDefNet", rgDefNetValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("rgNetType", rgNetTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("vinsType", vinsTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("sepFieldType", sepFieldTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("hwPath", hwPathValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("networkPlugin", networkPluginValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("networkPlugins", networkPluginsValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("strict_loose", strictLooseValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("interfaceState", interfaceStateValidator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,46 @@
|
|||||||
package validators
|
package validators
|
||||||
|
|
||||||
var (
|
var (
|
||||||
accountAccessTypeValues = []string{"R", "RCX", "ARCXDU"}
|
driverValues = []string{"KVM_X86", "KVM_PPC"}
|
||||||
accountCUTypeValues = []string{"CU_M", "CU_C", "CU_D", "CU_S", "CU_A", "CU_NO", "CU_I", "CU_NP"}
|
accessTypeValues = []string{"R", "RCX", "ARCXDU"}
|
||||||
|
resTypesValues = []string{"compute", "vins", "k8s", "openshift", "lb", "flipgroup"}
|
||||||
|
protoValues = []string{"tcp", "udp"}
|
||||||
|
|
||||||
bserviceDriverValues = []string{"KVM_X86, KVM_PPC"}
|
accountCUTypeValues = []string{"CU_M", "CU_C", "CU_D", "CU_S", "CU_A", "CU_NO", "CU_I", "CU_NP"}
|
||||||
bserviceModeValues = []string{"ABSOLUTE", "RELATIVE"}
|
|
||||||
|
|
||||||
computeTopologyValues = []string{"compute", "node"}
|
bserviceModeValues = []string{"ABSOLUTE", "RELATIVE"}
|
||||||
computePolicyValues = []string{"RECOMMENDED", "REQUIRED"}
|
|
||||||
computeModeValues = []string{"EQ", "EN", "ANY"}
|
computeTopologyValues = []string{"compute", "node"}
|
||||||
computeDiskTypeValues = []string{"D", "B"}
|
computePolicyValues = []string{"RECOMMENDED", "REQUIRED"}
|
||||||
computeNetTypeValues = []string{"EXTNET", "VINS"}
|
computeModeValues = []string{"EQ", "EN", "ANY"}
|
||||||
computeProtoValues = []string{"tcp", "udp"}
|
computeDiskTypeValues = []string{"D", "B"}
|
||||||
|
computeNetTypeValues = []string{"EXTNET", "VINS"}
|
||||||
|
computeOrderValues = []string{"cdrom", "network", "hd"}
|
||||||
|
computeDataDisksValues = []string{"KEEP", "DETACH", "DESTROY"}
|
||||||
|
|
||||||
|
diskTypeValues = []string{"B", "T", "D"}
|
||||||
|
|
||||||
|
flipgroupClientTypeValues = []string{"compute", "vins"}
|
||||||
|
|
||||||
|
kvmNetTypeValues = []string{"EXTNET", "VINS", "NONE"}
|
||||||
|
|
||||||
|
lbAlgorithmValues = []string{"roundrobin", "static-rr", "leastconn"}
|
||||||
|
|
||||||
|
rgDefNetValues = []string{"PRIVATE", "PUBLIC", "NONE"}
|
||||||
|
rgNetTypeValues = []string{"PUBLIC", "PRIVATE"}
|
||||||
|
|
||||||
|
vinsTypeValues = []string{"DHCP", "VIP", "EXCLUDE"}
|
||||||
|
|
||||||
imageBootTypeValues = []string{"uefi", "bios"}
|
imageBootTypeValues = []string{"uefi", "bios"}
|
||||||
imageTypeValues = []string{"windows", "linux", "other"}
|
imageTypeValues = []string{"windows", "linux", "other"}
|
||||||
imageDriversValues = []string{"KVM_X86"}
|
imageDriversValues = []string{"KVM_X86"}
|
||||||
imageArchitectureValues = []string{"X86_64", "PPC64_LE"}
|
imageArchitectureValues = []string{"X86_64", "PPC64_LE"}
|
||||||
|
|
||||||
|
sepFieldTypeValues = []string{"int", "str", "bool", "list", "dict"}
|
||||||
|
|
||||||
|
networkPluginValues = []string{"flannel", "weawenet", "calico"}
|
||||||
|
|
||||||
|
strictLooseValues = []string{"strict", "loose"}
|
||||||
|
|
||||||
|
interfaceStateValues = []string{"on", "off"}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type AddUserRequest struct {
|
|||||||
// - 'RCX' for Write
|
// - 'RCX' for Write
|
||||||
// - 'ARCXDU' for Admin
|
// - 'ARCXDU' for Admin
|
||||||
// Required: true
|
// Required: true
|
||||||
AccessType string `url:"accesstype" json:"accesstype" validate:"required,accountAccessType"`
|
AccessType string `url:"accesstype" json:"accesstype" validate:"required,accessType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddUser gives a user access rights.
|
// AddUser gives a user access rights.
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ type CreateRequest struct {
|
|||||||
|
|
||||||
// If true send emails when a user is granted access to resources
|
// If true send emails when a user is granted access to resources
|
||||||
// Required: false
|
// Required: false
|
||||||
SendAccessEmails bool `url:"sendAccessEmails,omitempty" json:"sendAccessEmails,omitempty"`
|
SendAccessEmails bool `url:"sendAccessEmails" json:"sendAccessEmails"`
|
||||||
|
|
||||||
// Limit (positive) or disable (0) GPU resources
|
// Limit (positive) or disable (0) GPU resources
|
||||||
// Required: false
|
// Required: false
|
||||||
|
|||||||
@@ -158,6 +158,12 @@ type RecordAccount struct {
|
|||||||
// Computes
|
// Computes
|
||||||
Computes Computes `json:"computes"`
|
Computes Computes `json:"computes"`
|
||||||
|
|
||||||
|
// CPU allocation parameter
|
||||||
|
CPUAllocationParameter string `json:"cpu_allocation_parameter"`
|
||||||
|
|
||||||
|
// CPU allocation ratio
|
||||||
|
CPUAllocationRatio float64 `json:"cpu_allocation_ratio"`
|
||||||
|
|
||||||
// Created by
|
// Created by
|
||||||
CreatedBy string `json:"createdBy"`
|
CreatedBy string `json:"createdBy"`
|
||||||
|
|
||||||
@@ -165,7 +171,7 @@ type RecordAccount struct {
|
|||||||
CreatedTime uint64 `json:"createdTime"`
|
CreatedTime uint64 `json:"createdTime"`
|
||||||
|
|
||||||
// Deactivation time
|
// Deactivation time
|
||||||
DeactivationTime uint64 `json:"deactivationTime"`
|
DeactivationTime float64 `json:"deactivationTime"`
|
||||||
|
|
||||||
// Deleted by
|
// Deleted by
|
||||||
DeletedBy string `json:"deletedBy"`
|
DeletedBy string `json:"deletedBy"`
|
||||||
@@ -192,7 +198,7 @@ type RecordAccount struct {
|
|||||||
ResourceLimits ResourceLimits `json:"resourceLimits"`
|
ResourceLimits ResourceLimits `json:"resourceLimits"`
|
||||||
|
|
||||||
// Resource types
|
// Resource types
|
||||||
ResourceTypes []string `json:"resourceTypes"`
|
ResTypes []string `json:"resourceTypes"`
|
||||||
|
|
||||||
// Send access emails
|
// Send access emails
|
||||||
SendAccessEmails bool `json:"sendAccessEmails"`
|
SendAccessEmails bool `json:"sendAccessEmails"`
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package account
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,15 +24,10 @@ func (a Account) Restore(ctx context.Context, req RestoreRequest) (bool, error)
|
|||||||
|
|
||||||
url := "/cloudapi/account/restore"
|
url := "/cloudapi/account/restore"
|
||||||
|
|
||||||
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
_, err = a.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
return true, nil
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,31 +20,31 @@ type UpdateRequest struct {
|
|||||||
|
|
||||||
// Max size of memory in MB
|
// Max size of memory in MB
|
||||||
// Required: false
|
// Required: false
|
||||||
MaxMemoryCapacity uint64 `url:"maxMemoryCapacity,omitempty" json:"maxMemoryCapacity,omitempty"`
|
MaxMemoryCapacity int64 `url:"maxMemoryCapacity,omitempty" json:"maxMemoryCapacity,omitempty"`
|
||||||
|
|
||||||
// Max size of aggregated vdisks in GB
|
// Max size of aggregated vdisks in GB
|
||||||
// Required: false
|
// Required: false
|
||||||
MaxVDiskCapacity uint64 `url:"maxVDiskCapacity,omitempty" json:"maxVDiskCapacity,omitempty"`
|
MaxVDiskCapacity int64 `url:"maxVDiskCapacity,omitempty" json:"maxVDiskCapacity,omitempty"`
|
||||||
|
|
||||||
// Max number of CPU cores
|
// Max number of CPU cores
|
||||||
// Required: false
|
// Required: false
|
||||||
MaxCPUCapacity uint64 `url:"maxCPUCapacity,omitempty" json:"maxCPUCapacity,omitempty"`
|
MaxCPUCapacity int64 `url:"maxCPUCapacity,omitempty" json:"maxCPUCapacity,omitempty"`
|
||||||
|
|
||||||
// Max sent/received network transfer peering
|
// Max sent/received network transfer peering
|
||||||
// Required: false
|
// Required: false
|
||||||
MaxNetworkPeerTransfer uint64 `url:"maxNetworkPeerTransfer,omitempty" json:"maxNetworkPeerTransfer,omitempty"`
|
MaxNetworkPeerTransfer int64 `url:"maxNetworkPeerTransfer,omitempty" json:"maxNetworkPeerTransfer,omitempty"`
|
||||||
|
|
||||||
// Max number of assigned public IPs
|
// Max number of assigned public IPs
|
||||||
// Required: false
|
// Required: false
|
||||||
MaxNumPublicIP uint64 `url:"maxNumPublicIP,omitempty" json:"maxNumPublicIP,omitempty"`
|
MaxNumPublicIP int64 `url:"maxNumPublicIP,omitempty" json:"maxNumPublicIP,omitempty"`
|
||||||
|
|
||||||
// If true send emails when a user is granted access to resources
|
// If true send emails when a user is granted access to resources
|
||||||
// Required: false
|
// Required: false
|
||||||
SendAccessEmails bool `url:"sendAccessEmails,omitempty" json:"sendAccessEmails,omitempty"`
|
SendAccessEmails bool `url:"sendAccessEmails" json:"sendAccessEmails"`
|
||||||
|
|
||||||
// Limit (positive) or disable (0) GPU resources
|
// Limit (positive) or disable (0) GPU resources
|
||||||
// Required: false
|
// Required: false
|
||||||
GPUUnits uint64 `url:"gpu_units,omitempty" json:"gpu_units,omitempty"`
|
GPUUnits int64 `url:"gpu_units,omitempty" json:"gpu_units,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates an account name and resource types and limits
|
// Update updates an account name and resource types and limits
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type UpdateUserRequest struct {
|
|||||||
// - 'RCX' for Write
|
// - 'RCX' for Write
|
||||||
// - 'ARCXDU' for Admin
|
// - 'ARCXDU' for Admin
|
||||||
// Required: true
|
// Required: true
|
||||||
AccessType string `url:"accesstype" json:"accesstype" validate:"required,accountAccessType"`
|
AccessType string `url:"accesstype" json:"accesstype" validate:"required,accessType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateUser updates user access rights
|
// UpdateUser updates user access rights
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ type GroupAddRequest struct {
|
|||||||
// - KVM_X86
|
// - KVM_X86
|
||||||
// - KVM_PPC
|
// - KVM_PPC
|
||||||
// Required: true
|
// Required: true
|
||||||
Driver string `url:"driver" json:"driver" validate:"bserviceDriver"`
|
Driver string `url:"driver" json:"driver" validate:"driver"`
|
||||||
|
|
||||||
// Storage endpoint provider ID
|
// Storage endpoint provider ID
|
||||||
// Required: false
|
// Required: false
|
||||||
|
|||||||
@@ -35,11 +35,8 @@ type RecordBasicService struct {
|
|||||||
// Grid ID
|
// Grid ID
|
||||||
GID uint64 `json:"gid"`
|
GID uint64 `json:"gid"`
|
||||||
|
|
||||||
// List of Service Compute Group IDs
|
// List of Service Compute Groups
|
||||||
Groups []uint64 `json:"groups"`
|
Groups ListGroups `json:"groups"`
|
||||||
|
|
||||||
// List of compute groups by name
|
|
||||||
GroupsName []string `json:"groupsName"`
|
|
||||||
|
|
||||||
// GUID
|
// GUID
|
||||||
GUID uint64 `json:"guid"`
|
GUID uint64 `json:"guid"`
|
||||||
@@ -95,6 +92,12 @@ type RecordBasicService struct {
|
|||||||
|
|
||||||
// Main information about Compute
|
// Main information about Compute
|
||||||
type ItemCompute struct {
|
type ItemCompute struct {
|
||||||
|
// Account ID
|
||||||
|
AccountID uint64
|
||||||
|
|
||||||
|
// Architecture
|
||||||
|
Architecture string `json:"arch"`
|
||||||
|
|
||||||
// Compute group ID
|
// Compute group ID
|
||||||
CompGroupID uint64 `json:"compgroupId"`
|
CompGroupID uint64 `json:"compgroupId"`
|
||||||
|
|
||||||
@@ -109,11 +112,47 @@ type ItemCompute struct {
|
|||||||
|
|
||||||
// Name
|
// Name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Resource group ID
|
||||||
|
RGID uint64 `json:"rgId"`
|
||||||
|
|
||||||
|
// StackID
|
||||||
|
StackID uint64 `json:"stackId"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Tech status
|
||||||
|
TechStatus string `json:"techStatus"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of Computes
|
// List of Computes
|
||||||
type ListComputes []ItemCompute
|
type ListComputes []ItemCompute
|
||||||
|
|
||||||
|
// Main information about Group
|
||||||
|
type ItemGroup struct {
|
||||||
|
// Amount of computes
|
||||||
|
Computes uint64 `json:"computes"`
|
||||||
|
|
||||||
|
// Consistency
|
||||||
|
Consistency bool `json:"consistency"`
|
||||||
|
|
||||||
|
// Group ID
|
||||||
|
ID uint64 `json:"id"`
|
||||||
|
|
||||||
|
// Group name
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// TechStatus
|
||||||
|
TechStatus string `json:"techStatus"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of Groups
|
||||||
|
type ListGroups []ItemGroup
|
||||||
|
|
||||||
// Main information about Snapshot
|
// Main information about Snapshot
|
||||||
type ItemSnapshot struct {
|
type ItemSnapshot struct {
|
||||||
// GUID
|
// GUID
|
||||||
|
|||||||
41
pkg/cloudapi/compute/boot_order_get.go
Normal file
41
pkg/cloudapi/compute/boot_order_get.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request struct for getting boot order
|
||||||
|
type BootOrderGetRequest struct {
|
||||||
|
// Compute ID
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BootOrderGet gets actual compute boot order information
|
||||||
|
func (c Compute) BootOrderGet(ctx context.Context, req BootOrderGetRequest) ([]string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/compute/bootOrderGet"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
orders := make([]string, 0)
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &orders)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return orders, nil
|
||||||
|
}
|
||||||
49
pkg/cloudapi/compute/boot_order_set.go
Normal file
49
pkg/cloudapi/compute/boot_order_set.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request struct for setting boot order
|
||||||
|
type BootOrderSetRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
|
||||||
|
|
||||||
|
// List of boot devices
|
||||||
|
// Should be one of:
|
||||||
|
// - cdrom
|
||||||
|
// - network
|
||||||
|
// - hd
|
||||||
|
// Required: true
|
||||||
|
Order []string `url:"order" json:"order" validate:"min=1,computeOrder"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BootOrderSet sets compute boot order
|
||||||
|
func (c Compute) BootOrderSet(ctx context.Context, req BootOrderSetRequest) ([]string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/compute/bootOrderSet"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
orders := make([]string, 0)
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &orders)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return orders, nil
|
||||||
|
}
|
||||||
47
pkg/cloudapi/compute/change_link_state.go
Normal file
47
pkg/cloudapi/compute/change_link_state.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Request struct for changing link state
|
||||||
|
type ChangeLinkStateRequest struct {
|
||||||
|
// Compute ID
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
|
||||||
|
|
||||||
|
// Interface name or MAC address
|
||||||
|
// Required: true
|
||||||
|
Interface string `url:"interface" json:"interface" validate:"required"`
|
||||||
|
|
||||||
|
// Interface state
|
||||||
|
// Must be either "on" or "off"
|
||||||
|
// Required: true
|
||||||
|
State string `url:"state" json:"state" validate:"required,interfaceState"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeLinkState changes the status link virtual of compute
|
||||||
|
func (c Compute) ChangeLinkState(ctx context.Context, req ChangeLinkStateRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/compute/changeLinkState"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.ParseBool(string(res))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -18,12 +18,12 @@ type CreateTemplateRequest struct {
|
|||||||
// Name to assign to the template being created
|
// Name to assign to the template being created
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name" validate:"required"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
// Async API call
|
type wrapperCreateTemplateRequest struct {
|
||||||
// For async call use CreateTemplateAsync
|
CreateTemplateRequest
|
||||||
// For sync call use CreateTemplate
|
|
||||||
// Required: true
|
Async bool `url:"async"`
|
||||||
async bool `url:"async"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplate create template from compute instance
|
// CreateTemplate create template from compute instance
|
||||||
@@ -35,11 +35,14 @@ func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req.async = false
|
reqWrapped := wrapperCreateTemplateRequest{
|
||||||
|
CreateTemplateRequest: req,
|
||||||
|
Async: false,
|
||||||
|
}
|
||||||
|
|
||||||
url := "/cloudapi/compute/createTemplate"
|
url := "/cloudapi/compute/createTemplate"
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -61,11 +64,14 @@ func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req.async = true
|
reqWrapped := wrapperCreateTemplateRequest{
|
||||||
|
CreateTemplateRequest: req,
|
||||||
|
Async: true,
|
||||||
|
}
|
||||||
|
|
||||||
url := "/cloudapi/compute/createTemplate"
|
url := "/cloudapi/compute/createTemplate"
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ type DiskAddRequest struct {
|
|||||||
// Required: true
|
// Required: true
|
||||||
Size uint64 `url:"size" json:"size" validate:"required"`
|
Size uint64 `url:"size" json:"size" validate:"required"`
|
||||||
|
|
||||||
|
// Storage endpoint provider ID
|
||||||
|
// By default the same with boot disk
|
||||||
|
// Required: false
|
||||||
|
SepID uint64 `url:"sepId,omitempty" json:"sepId,omitempty"`
|
||||||
|
|
||||||
// Type of the disk
|
// Type of the disk
|
||||||
// Should be one of:
|
// Should be one of:
|
||||||
// - D
|
// - D
|
||||||
@@ -29,11 +34,6 @@ type DiskAddRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty" validate:"omitempty,computeDiskType"`
|
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty" validate:"omitempty,computeDiskType"`
|
||||||
|
|
||||||
// Storage endpoint provider ID
|
|
||||||
// By default the same with boot disk
|
|
||||||
// Required: false
|
|
||||||
SepID uint64 `url:"sepId,omitempty" json:"sepId,omitempty"`
|
|
||||||
|
|
||||||
// Pool name
|
// Pool name
|
||||||
// By default will be chosen automatically
|
// By default will be chosen automatically
|
||||||
// Required: false
|
// Required: false
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ type DiskAttachRequest struct {
|
|||||||
// ID of the disk to attach
|
// ID of the disk to attach
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
|
// Type of the disk B;D
|
||||||
|
// Required: false
|
||||||
|
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty" validate:"omitempty,computeDiskType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskAttach attach disk to compute
|
// DiskAttach attach disk to compute
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
package compute
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/lb"
|
||||||
|
)
|
||||||
|
|
||||||
// FilterByID returns ListComputes with specified ID.
|
// FilterByID returns ListComputes with specified ID.
|
||||||
func (lc ListComputes) FilterByID(id uint64) ListComputes {
|
func (lc ListComputes) FilterByID(id uint64) ListComputes {
|
||||||
predicate := func(ic ItemCompute) bool {
|
predicate := func(ic ItemCompute) bool {
|
||||||
@@ -36,7 +44,7 @@ func (lc ListComputes) FilterByTechStatus(techStatus string) ListComputes {
|
|||||||
return lc.FilterFunc(predicate)
|
return lc.FilterFunc(predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterByDiskID return ListComputes with specified DiskID.
|
// FilterByDiskID returns ListComputes with specified DiskID.
|
||||||
func (lc ListComputes) FilterByDiskID(diskID uint64) ListComputes {
|
func (lc ListComputes) FilterByDiskID(diskID uint64) ListComputes {
|
||||||
predicate := func(ic ItemCompute) bool {
|
predicate := func(ic ItemCompute) bool {
|
||||||
for _, disk := range ic.Disks {
|
for _, disk := range ic.Disks {
|
||||||
@@ -50,6 +58,88 @@ func (lc ListComputes) FilterByDiskID(diskID uint64) ListComputes {
|
|||||||
return lc.FilterFunc(predicate)
|
return lc.FilterFunc(predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterByK8SID returns master and worker nodes (ListComputes) inside specified K8S cluster.
|
||||||
|
func (lc ListComputes) FilterByK8SID(ctx context.Context, k8sID uint64, decortClient interfaces.Caller) (ListComputes, error) {
|
||||||
|
caller := k8s.New(decortClient)
|
||||||
|
|
||||||
|
req := k8s.GetRequest{
|
||||||
|
K8SID: k8sID,
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster, err := caller.Get(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate := func(ic ItemCompute) bool {
|
||||||
|
for _, info := range cluster.K8SGroups.Masters.DetailedInfo {
|
||||||
|
if info.ID == ic.ID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, worker := range cluster.K8SGroups.Workers {
|
||||||
|
for _, info := range worker.DetailedInfo {
|
||||||
|
if info.ID == ic.ID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return lc.FilterFunc(predicate), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// K8SMasters is used to filter master nodes. Best used after FilterByK8SID function.
|
||||||
|
func (lc ListComputes) FilterByK8SMasters() ListComputes {
|
||||||
|
predicate := func(ic ItemCompute) bool {
|
||||||
|
for _, rule := range ic.AntiAffinityRules {
|
||||||
|
if rule.Value == "master" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return lc.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// K8SMasters is used to filter worker nodes. Best used after FilterByK8SID function.
|
||||||
|
func (lc ListComputes) FilterByK8SWorkers() ListComputes {
|
||||||
|
predicate := func(ic ItemCompute) bool {
|
||||||
|
for _, rule := range ic.AntiAffinityRules {
|
||||||
|
if rule.Value == "worker" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return lc.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByLBID returns ListComputes used by specified Load Balancer.
|
||||||
|
func (lc ListComputes) FilterByLBID(ctx context.Context, lbID uint64, decortClient interfaces.Caller) (ListComputes, error) {
|
||||||
|
caller := lb.New(decortClient)
|
||||||
|
|
||||||
|
req := lb.GetRequest{
|
||||||
|
LBID: lbID,
|
||||||
|
}
|
||||||
|
|
||||||
|
foundLB, err := caller.Get(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate := func(ic ItemCompute) bool {
|
||||||
|
return ic.ID == foundLB.PrimaryNode.ComputeID || ic.ID == foundLB.SecondaryNode.ComputeID
|
||||||
|
}
|
||||||
|
|
||||||
|
return lc.FilterFunc(predicate), nil
|
||||||
|
}
|
||||||
|
|
||||||
// FilterFunc allows filtering ListComputes based on a user-specified predicate.
|
// FilterFunc allows filtering ListComputes based on a user-specified predicate.
|
||||||
func (lc ListComputes) FilterFunc(predicate func(ItemCompute) bool) ListComputes {
|
func (lc ListComputes) FilterFunc(predicate func(ItemCompute) bool) ListComputes {
|
||||||
var result ListComputes
|
var result ListComputes
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import "testing"
|
|||||||
|
|
||||||
var computes = ListComputes{
|
var computes = ListComputes{
|
||||||
ItemCompute{
|
ItemCompute{
|
||||||
ACL: []interface{}{},
|
ACL: ListACL{},
|
||||||
AccountID: 132847,
|
AccountID: 132847,
|
||||||
AccountName: "std_2",
|
AccountName: "std_2",
|
||||||
AffinityLabel: "",
|
AffinityLabel: "",
|
||||||
@@ -85,7 +85,7 @@ var computes = ListComputes{
|
|||||||
VirtualImageID: 0,
|
VirtualImageID: 0,
|
||||||
},
|
},
|
||||||
ItemCompute{
|
ItemCompute{
|
||||||
ACL: []interface{}{},
|
ACL: ListACL{},
|
||||||
AccountID: 132848,
|
AccountID: 132848,
|
||||||
AccountName: "std_broker",
|
AccountName: "std_broker",
|
||||||
AffinityLabel: "",
|
AffinityLabel: "",
|
||||||
@@ -150,92 +150,92 @@ var computes = ListComputes{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterByID(t *testing.T) {
|
func TestFilterByID(t *testing.T) {
|
||||||
actual := computes.FilterByID(48500).FindOne()
|
actual := computes.FilterByID(48500).FindOne()
|
||||||
|
|
||||||
if actual.ID != 48500 {
|
if actual.ID != 48500 {
|
||||||
t.Fatal("expected ID 48500, found: ", actual.ID)
|
t.Fatal("expected ID 48500, found: ", actual.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
actualEmpty := computes.FilterByID(0)
|
actualEmpty := computes.FilterByID(0)
|
||||||
|
|
||||||
if len(actualEmpty) != 0 {
|
if len(actualEmpty) != 0 {
|
||||||
t.Fatal("expected empty, actual: ", len(actualEmpty))
|
t.Fatal("expected empty, actual: ", len(actualEmpty))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterByName(t *testing.T) {
|
func TestFilterByName(t *testing.T) {
|
||||||
actual := computes.FilterByName("test").FindOne()
|
actual := computes.FilterByName("test").FindOne()
|
||||||
|
|
||||||
if actual.Name != "test" {
|
if actual.Name != "test" {
|
||||||
t.Fatal("expected compute with name 'test', found: ", actual.Name)
|
t.Fatal("expected compute with name 'test', found: ", actual.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterByStatus(t *testing.T) {
|
func TestFilterByStatus(t *testing.T) {
|
||||||
actual := computes.FilterByStatus("ENABLED")
|
actual := computes.FilterByStatus("ENABLED")
|
||||||
|
|
||||||
for _, item := range actual {
|
for _, item := range actual {
|
||||||
if item.Status != "ENABLED" {
|
if item.Status != "ENABLED" {
|
||||||
t.Fatal("expected ENABLED status, found: ", item.Status)
|
t.Fatal("expected ENABLED status, found: ", item.Status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterByTechStatus(t *testing.T) {
|
func TestFilterByTechStatus(t *testing.T) {
|
||||||
actual := computes.FilterByTechStatus("STARTED").FindOne()
|
actual := computes.FilterByTechStatus("STARTED").FindOne()
|
||||||
|
|
||||||
if actual.ID != 48556 {
|
if actual.ID != 48556 {
|
||||||
t.Fatal("expected 48556 with STARTED techStatus, found: ", actual.ID)
|
t.Fatal("expected 48556 with STARTED techStatus, found: ", actual.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterByDiskID(t *testing.T) {
|
func TestFilterByDiskID(t *testing.T) {
|
||||||
actual := computes.FilterByDiskID(65248).FindOne()
|
actual := computes.FilterByDiskID(65248).FindOne()
|
||||||
|
|
||||||
if actual.ID != 48556 {
|
if actual.ID != 48556 {
|
||||||
t.Fatal("expected 48556 with DiskID 65248, found: ", actual.ID)
|
t.Fatal("expected 48556 with DiskID 65248, found: ", actual.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterFunc(t *testing.T) {
|
func TestFilterFunc(t *testing.T) {
|
||||||
actual := computes.FilterFunc(func(ic ItemCompute) bool {
|
actual := computes.FilterFunc(func(ic ItemCompute) bool {
|
||||||
return ic.Registered == true
|
return ic.Registered == true
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(actual) != 2 {
|
if len(actual) != 2 {
|
||||||
t.Fatal("expected 2 elements found, actual: ", len(actual))
|
t.Fatal("expected 2 elements found, actual: ", len(actual))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range actual {
|
for _, item := range actual {
|
||||||
if item.Registered != true {
|
if item.Registered != true {
|
||||||
t.Fatal("expected Registered to be true, actual: ", item.Registered)
|
t.Fatal("expected Registered to be true, actual: ", item.Registered)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortingByCreatedTime(t *testing.T) {
|
func TestSortingByCreatedTime(t *testing.T) {
|
||||||
actual := computes.SortByCreatedTime(false)
|
actual := computes.SortByCreatedTime(false)
|
||||||
|
|
||||||
if actual[0].Name != "test" {
|
if actual[0].Name != "test" {
|
||||||
t.Fatal("expected 'test', found: ", actual[0].Name)
|
t.Fatal("expected 'test', found: ", actual[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = computes.SortByCreatedTime(true)
|
actual = computes.SortByCreatedTime(true)
|
||||||
if actual[0].Name != "compute_2" {
|
if actual[0].Name != "compute_2" {
|
||||||
t.Fatal("expected 'compute_2', found: ", actual[0].Name)
|
t.Fatal("expected 'compute_2', found: ", actual[0].Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSortingByCPU(t *testing.T) {
|
func TestSortingByCPU(t *testing.T) {
|
||||||
actual := computes.SortByCPU(false)
|
actual := computes.SortByCPU(false)
|
||||||
|
|
||||||
if actual[0].CPU != 4{
|
if actual[0].CPU != 4 {
|
||||||
t.Fatal("expected 4 CPU cores, found: ", actual[0].CPU)
|
t.Fatal("expected 4 CPU cores, found: ", actual[0].CPU)
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = computes.SortByCPU(true)
|
actual = computes.SortByCPU(true)
|
||||||
|
|
||||||
if actual[0].CPU != 6 {
|
if actual[0].CPU != 6 {
|
||||||
t.Fatal("expected 6 CPU cores, found: ", actual[0].CPU)
|
t.Fatal("expected 6 CPU cores, found: ", actual[0].CPU)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package compute
|
package compute
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
// Access Control List
|
// Access Control List
|
||||||
type RecordACL struct {
|
type RecordACL struct {
|
||||||
// Account ACL list
|
// Account ACL list
|
||||||
@@ -12,10 +14,27 @@ type RecordACL struct {
|
|||||||
RGACL ListACL `json:"rgAcl"`
|
RGACL ListACL `json:"rgAcl"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Explicit bool
|
||||||
|
|
||||||
|
func (e *Explicit) UnmarshalJSON(b []byte) error {
|
||||||
|
if b[0] == '"' {
|
||||||
|
b = b[1 : len(b)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := strconv.ParseBool(string(b))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = Explicit(res)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ACL information
|
// ACL information
|
||||||
type ItemACL struct {
|
type ItemACL struct {
|
||||||
// Explicit
|
// Explicit
|
||||||
Explicit bool `json:"explicit"`
|
Explicit Explicit `json:"explicit"`
|
||||||
|
|
||||||
// GUID
|
// GUID
|
||||||
GUID string `json:"guid"`
|
GUID string `json:"guid"`
|
||||||
@@ -131,6 +150,9 @@ type RecordNetAttach struct {
|
|||||||
// Default GW
|
// Default GW
|
||||||
DefGW string `json:"defGw"`
|
DefGW string `json:"defGw"`
|
||||||
|
|
||||||
|
// Enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
FLIPGroupID uint64 `json:"flipgroupId"`
|
FLIPGroupID uint64 `json:"flipgroupId"`
|
||||||
|
|
||||||
@@ -159,7 +181,7 @@ type RecordNetAttach struct {
|
|||||||
NetType string `json:"netType"`
|
NetType string `json:"netType"`
|
||||||
|
|
||||||
// PCI slot
|
// PCI slot
|
||||||
PCISlot uint64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
// QOS
|
// QOS
|
||||||
QOS QOS `json:"qos"`
|
QOS QOS `json:"qos"`
|
||||||
@@ -464,6 +486,9 @@ type ItemVNFInterface struct {
|
|||||||
// Default GW
|
// Default GW
|
||||||
DefGW string `json:"defGw"`
|
DefGW string `json:"defGw"`
|
||||||
|
|
||||||
|
// Enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
FLIPGroupID uint64 `json:"flipgroupId"`
|
FLIPGroupID uint64 `json:"flipgroupId"`
|
||||||
|
|
||||||
@@ -492,7 +517,7 @@ type ItemVNFInterface struct {
|
|||||||
NetType string `json:"netType"`
|
NetType string `json:"netType"`
|
||||||
|
|
||||||
// PCI slot
|
// PCI slot
|
||||||
PCISlot uint64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
// QOS
|
// QOS
|
||||||
QOS QOS `json:"qos"`
|
QOS QOS `json:"qos"`
|
||||||
@@ -592,7 +617,7 @@ type ItemComputeDisk struct {
|
|||||||
Passwd string `json:"passwd"`
|
Passwd string `json:"passwd"`
|
||||||
|
|
||||||
// PCI slot
|
// PCI slot
|
||||||
PCISlot uint64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
// Pool
|
// Pool
|
||||||
Pool string `json:"pool"`
|
Pool string `json:"pool"`
|
||||||
@@ -709,8 +734,7 @@ type IOTune struct {
|
|||||||
// Main information about compute
|
// Main information about compute
|
||||||
type ItemCompute struct {
|
type ItemCompute struct {
|
||||||
// Access Control List
|
// Access Control List
|
||||||
ACL []interface{} `json:"acl"`
|
ACL ListACL `json:"acl"`
|
||||||
|
|
||||||
// Account ID
|
// Account ID
|
||||||
AccountID uint64 `json:"accountId"`
|
AccountID uint64 `json:"accountId"`
|
||||||
|
|
||||||
@@ -877,7 +901,7 @@ type InfoDisk struct {
|
|||||||
ID uint64 `json:"id"`
|
ID uint64 `json:"id"`
|
||||||
|
|
||||||
// PCISlot
|
// PCISlot
|
||||||
PCISlot uint64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List information about computes
|
// List information about computes
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ type PFWAddRequest struct {
|
|||||||
PublicPortStart uint64 `url:"publicPortStart" json:"publicPortStart" validate:"required"`
|
PublicPortStart uint64 `url:"publicPortStart" json:"publicPortStart" validate:"required"`
|
||||||
|
|
||||||
// End port number (inclusive) for the ranged rule
|
// End port number (inclusive) for the ranged rule
|
||||||
|
// Default value: -1
|
||||||
// Required: false
|
// Required: false
|
||||||
PublicPortEnd uint64 `url:"publicPortEnd,omitempty" json:"publicPortEnd,omitempty"`
|
PublicPortEnd int64 `url:"publicPortEnd,omitempty" json:"publicPortEnd,omitempty"`
|
||||||
|
|
||||||
// Internal base port number
|
// Internal base port number
|
||||||
// Required: true
|
// Required: true
|
||||||
@@ -29,7 +30,7 @@ type PFWAddRequest struct {
|
|||||||
// Network protocol
|
// Network protocol
|
||||||
// either "tcp" or "udp"
|
// either "tcp" or "udp"
|
||||||
// Required: true
|
// Required: true
|
||||||
Proto string `url:"proto" json:"proto" validate:"computeProto"`
|
Proto string `url:"proto" json:"proto" validate:"proto"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PFWAdd add port forward rule
|
// PFWAdd add port forward rule
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type UserGrantRequest struct {
|
|||||||
// - 'RCX' for Write
|
// - 'RCX' for Write
|
||||||
// - 'ARCXDU' for Admin
|
// - 'ARCXDU' for Admin
|
||||||
// Required: true
|
// Required: true
|
||||||
AccessType string `url:"accesstype" json:"accesstype" validate:"accountAccessType"`
|
AccessType string `url:"accesstype" json:"accesstype" validate:"accessType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserGrant grant user access to the compute
|
// UserGrant grant user access to the compute
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type UserUpdateRequest struct {
|
|||||||
// - 'RCX' for Write
|
// - 'RCX' for Write
|
||||||
// - 'ARCXDU' for Admin
|
// - 'ARCXDU' for Admin
|
||||||
// Required: true
|
// Required: true
|
||||||
AccessType string `url:"accesstype" json:"accesstype" validate:"accountAccessType"`
|
AccessType string `url:"accesstype" json:"accesstype" validate:"accessType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserUpdate updates user access to the compute
|
// UserUpdate updates user access to the compute
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@@ -13,15 +12,15 @@ import (
|
|||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
// ID of the account
|
// ID of the account
|
||||||
// Required: true
|
// Required: true
|
||||||
AccountID uint64 `url:"accountId" json:"accountId"`
|
AccountID uint64 `url:"accountId" json:"accountId" validate:"required"`
|
||||||
|
|
||||||
// ID of the grid (platform)
|
// ID of the grid (platform)
|
||||||
// Required: true
|
// Required: true
|
||||||
GID uint64 `url:"gid" json:"gid"`
|
GID uint64 `url:"gid" json:"gid" validate:"required"`
|
||||||
|
|
||||||
// Name of disk
|
// Name of disk
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Description of disk
|
// Description of disk
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -36,7 +35,7 @@ type CreateRequest struct {
|
|||||||
// - D=Data
|
// - D=Data
|
||||||
// - T=Temp
|
// - T=Temp
|
||||||
// Required: true
|
// Required: true
|
||||||
Type string `url:"type" json:"type"`
|
Type string `url:"type" json:"type" validate:"diskType"`
|
||||||
|
|
||||||
// Size in GB default is 0
|
// Size in GB default is 0
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -55,29 +54,13 @@ type CreateRequest struct {
|
|||||||
Pool string `url:"pool,omitempty" json:"pool,omitempty"`
|
Pool string `url:"pool,omitempty" json:"pool,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (drq CreateRequest) validate() error {
|
|
||||||
if drq.AccountID == 0 {
|
|
||||||
return errors.New("validation-error: field AccountID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if drq.GID == 0 {
|
|
||||||
return errors.New("validation-error: field GID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if drq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
validType := validators.StringInSlice(drq.Type, []string{"B", "D", "T"})
|
|
||||||
if !validType {
|
|
||||||
return errors.New("validation-error: field Type must be set as B, D or T")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates a disk
|
// Create creates a disk
|
||||||
func (d Disks) Create(ctx context.Context, req CreateRequest) (uint64, error) {
|
func (d Disks) Create(ctx context.Context, req CreateRequest) (uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return 0, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/create"
|
url := "/cloudapi/disks/create"
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request for delete disk
|
// Request for delete disk
|
||||||
type DeleteRequest struct {
|
type DeleteRequest struct {
|
||||||
// ID of disk to delete
|
// ID of disk to delete
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// Detach disk from machine first
|
// Detach disk from machine first
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -26,19 +27,13 @@ type DeleteRequest struct {
|
|||||||
Reason string `url:"reason,omitempty" json:"reason,omitempty"`
|
Reason string `url:"reason,omitempty" json:"reason,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d DeleteRequest) validate() error {
|
|
||||||
if d.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete deletes disk by ID
|
// Delete deletes disk by ID
|
||||||
func (d Disks) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
func (d Disks) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/delete"
|
url := "/cloudapi/disks/delete"
|
||||||
|
|||||||
@@ -2,42 +2,34 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for multiple disks
|
// Request struct for multiple disks
|
||||||
type DisksDeleteRequest struct {
|
type DisksDeleteRequest struct {
|
||||||
// List of disk ids to delete
|
// List of disk ids to delete
|
||||||
// Required: true
|
// Required: true
|
||||||
DisksIDs []uint64 `url:"diskIds" json:"diskIds"`
|
DisksIDs []uint64 `url:"diskIds" json:"diskIds" validate:"required"`
|
||||||
|
|
||||||
// Reason for deleting the disks
|
// Reason for deleting the disks
|
||||||
// Required: true
|
// Required: true
|
||||||
Reason string `url:"reason" json:"reason"`
|
Reason string `url:"reason" json:"reason" validate:"required"`
|
||||||
|
|
||||||
// Whether to completely delete the disks, works only with non attached disks
|
// Whether to completely delete the disks, works only with non attached disks
|
||||||
// Required: false
|
// Required: false
|
||||||
Permanently bool `url:"permanently,omitempty" json:"permanently,omitempty"`
|
Permanently bool `url:"permanently,omitempty" json:"permanently,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (drq DisksDeleteRequest) validate() error {
|
|
||||||
if len(drq.DisksIDs) == 0 {
|
|
||||||
return errors.New("validation-error: field DisksIDs must include one or more disks ids")
|
|
||||||
}
|
|
||||||
if drq.Reason == "" {
|
|
||||||
return errors.New("validation-error: field Reason must be set")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDisks deletes multiple disks permanently
|
// DeleteDisks deletes multiple disks permanently
|
||||||
func (d Disks) DeleteDisks(ctx context.Context, req DisksDeleteRequest) (bool, error) {
|
func (d Disks) DeleteDisks(ctx context.Context, req DisksDeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/deleteDisks"
|
url := "/cloudapi/disks/deleteDisks"
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package disks
|
package disks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/lb"
|
||||||
|
)
|
||||||
|
|
||||||
// FilterByID returns ListDisks with specified ID.
|
// FilterByID returns ListDisks with specified ID.
|
||||||
func (ld ListDisks) FilterByID(id uint64) ListDisks {
|
func (ld ListDisks) FilterByID(id uint64) ListDisks {
|
||||||
predicate := func(idisk ItemDisk) bool {
|
predicate := func(idisk ItemDisk) bool {
|
||||||
@@ -36,6 +45,69 @@ func (ld ListDisks) FilterByTechStatus(techStatus string) ListDisks {
|
|||||||
return ld.FilterFunc(predicate)
|
return ld.FilterFunc(predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterByComputeID is used to filter ListDisks attached to specified compute.
|
||||||
|
func (ld ListDisks) FilterByComputeID(computeID uint64) ListDisks {
|
||||||
|
predicate := func(idisk ItemDisk) bool {
|
||||||
|
for k := range idisk.Computes {
|
||||||
|
if k == strconv.FormatUint(computeID, 10) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return ld.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByK8SID is used to filter ListDisks by specified K8S cluster.
|
||||||
|
func (ld ListDisks) FilterByK8SID(ctx context.Context, k8sID uint64, decortClient interfaces.Caller) (ListDisks, error) {
|
||||||
|
caller := k8s.New(decortClient)
|
||||||
|
|
||||||
|
req := k8s.GetRequest{
|
||||||
|
K8SID: k8sID,
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster, err := caller.Get(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result ListDisks
|
||||||
|
|
||||||
|
for _, masterCompute := range cluster.K8SGroups.Masters.DetailedInfo {
|
||||||
|
result = append(result, ld.FilterByComputeID(masterCompute.ID)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, workerGroup := range cluster.K8SGroups.Workers {
|
||||||
|
for _, workerCompute := range workerGroup.DetailedInfo {
|
||||||
|
result = append(result, ld.FilterByComputeID(workerCompute.ID)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByLBID is used to filter ListDisks used by computes inside specified Load Balancer.
|
||||||
|
func (ld ListDisks) FilterByLBID(ctx context.Context, lbID uint64, decortClient interfaces.Caller) (ListDisks, error) {
|
||||||
|
caller := lb.New(decortClient)
|
||||||
|
|
||||||
|
req := lb.GetRequest{
|
||||||
|
LBID: lbID,
|
||||||
|
}
|
||||||
|
|
||||||
|
foundLB, err := caller.Get(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result ListDisks
|
||||||
|
result = append(result, ld.FilterByComputeID(foundLB.PrimaryNode.ComputeID)...)
|
||||||
|
result = append(result, ld.FilterByComputeID(foundLB.SecondaryNode.ComputeID)...)
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
// FilterFunc allows filtering ListDisks based on a user-specified predicate.
|
// FilterFunc allows filtering ListDisks based on a user-specified predicate.
|
||||||
func (ld ListDisks) FilterFunc(predicate func(ItemDisk) bool) ListDisks {
|
func (ld ListDisks) FilterFunc(predicate func(ItemDisk) bool) ListDisks {
|
||||||
var result ListDisks
|
var result ListDisks
|
||||||
@@ -58,3 +130,62 @@ func (ld ListDisks) FindOne() ItemDisk {
|
|||||||
|
|
||||||
return ld[0]
|
return ld[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterByID returns ListDisksUnattached with specified ID.
|
||||||
|
func (lu ListDisksUnattached) FilterByID(id uint64) ListDisksUnattached {
|
||||||
|
predicate := func(idisk ItemDiskUnattached) bool {
|
||||||
|
return idisk.ID == id
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByName returns ListDisksUnattached with specified Name.
|
||||||
|
func (lu ListDisksUnattached) FilterByName(name string) ListDisksUnattached {
|
||||||
|
predicate := func(idisk ItemDiskUnattached) bool {
|
||||||
|
return idisk.Name == name
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByStatus returns ListDisksUnattached with specified Status.
|
||||||
|
func (lu ListDisksUnattached) FilterByStatus(status string) ListDisksUnattached {
|
||||||
|
predicate := func(idisk ItemDiskUnattached) bool {
|
||||||
|
return idisk.Status == status
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByTechStatus returns ListDisksUnattached with specified TechStatus.
|
||||||
|
func (lu ListDisksUnattached) FilterByTechStatus(techStatus string) ListDisksUnattached {
|
||||||
|
predicate := func(idisk ItemDiskUnattached) bool {
|
||||||
|
return idisk.TechStatus == techStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering ListDisksUnattached based on a user-specified predicate.
|
||||||
|
func (lu ListDisksUnattached) FilterFunc(predicate func(ItemDiskUnattached) bool) ListDisksUnattached {
|
||||||
|
var result ListDisksUnattached
|
||||||
|
|
||||||
|
for _, item := range lu {
|
||||||
|
if predicate(item) {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first found ItemDiskUnattached
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (lu ListDisksUnattached) FindOne() ItemDiskUnattached {
|
||||||
|
if len(lu) == 0 {
|
||||||
|
return ItemDiskUnattached{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu[0]
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package disks
|
package disks
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
var disks = ListDisks{
|
var disks = ListDisks{
|
||||||
ItemDisk{
|
ItemDisk{
|
||||||
@@ -175,3 +177,198 @@ func TestSortByCreatedTime(t *testing.T) {
|
|||||||
t.Fatal("expected ID 65193, found: ", actual[0].ID)
|
t.Fatal("expected ID 65193, found: ", actual[0].ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unattachedDisks = ListDisksUnattached{
|
||||||
|
{
|
||||||
|
CKey: "",
|
||||||
|
Meta: []interface{}{
|
||||||
|
"cloudbroker",
|
||||||
|
"disk",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
AccountID: 149,
|
||||||
|
AccountName: "test_account1",
|
||||||
|
ACL: map[string]interface{}{},
|
||||||
|
BootPartition: 0,
|
||||||
|
CreatedTime: 1681477547,
|
||||||
|
DeletedTime: 0,
|
||||||
|
Description: "",
|
||||||
|
DestructionTime: 0,
|
||||||
|
DiskPath: "",
|
||||||
|
GID: 2002,
|
||||||
|
GUID: 22636,
|
||||||
|
ID: 22636,
|
||||||
|
ImageID: 0,
|
||||||
|
Images: []uint64{},
|
||||||
|
IOTune: IOTune{
|
||||||
|
TotalIOPSSec: 2000,
|
||||||
|
},
|
||||||
|
IQN: "",
|
||||||
|
Login: "",
|
||||||
|
Milestones: 43834,
|
||||||
|
Name: "test_disk",
|
||||||
|
Order: 0,
|
||||||
|
Params: "",
|
||||||
|
ParentID: 0,
|
||||||
|
Password: "",
|
||||||
|
PCISlot: -1,
|
||||||
|
Pool: "data05",
|
||||||
|
PresentTo: []uint64{},
|
||||||
|
PurgeAttempts: 0,
|
||||||
|
PurgeTime: 0,
|
||||||
|
RealityDeviceNumber: 0,
|
||||||
|
ReferenceID: "",
|
||||||
|
ResID: "79bd3bd8-3424-48d3-963f-1870d506f169",
|
||||||
|
ResName: "volumes/volume_22636",
|
||||||
|
Role: "",
|
||||||
|
SEPID: 1,
|
||||||
|
Shareable: false,
|
||||||
|
SizeMax: 0,
|
||||||
|
SizeUsed: 0,
|
||||||
|
Snapshots: nil,
|
||||||
|
Status: "CREATED",
|
||||||
|
TechStatus: "ALLOCATED",
|
||||||
|
Type: "D",
|
||||||
|
VMID: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
CKey: "",
|
||||||
|
Meta: []interface{}{
|
||||||
|
"cloudbroker",
|
||||||
|
"disk",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
AccountID: 150,
|
||||||
|
AccountName: "test_account",
|
||||||
|
ACL: map[string]interface{}{},
|
||||||
|
BootPartition: 0,
|
||||||
|
CreatedTime: 1681477558,
|
||||||
|
DeletedTime: 0,
|
||||||
|
Description: "",
|
||||||
|
DestructionTime: 0,
|
||||||
|
DiskPath: "",
|
||||||
|
GID: 2002,
|
||||||
|
GUID: 22637,
|
||||||
|
ID: 22637,
|
||||||
|
ImageID: 0,
|
||||||
|
Images: []uint64{},
|
||||||
|
IOTune: IOTune{
|
||||||
|
TotalIOPSSec: 2000,
|
||||||
|
},
|
||||||
|
IQN: "",
|
||||||
|
Login: "",
|
||||||
|
Milestones: 43834,
|
||||||
|
Name: "test_disk",
|
||||||
|
Order: 0,
|
||||||
|
Params: "",
|
||||||
|
ParentID: 0,
|
||||||
|
Password: "",
|
||||||
|
PCISlot: -1,
|
||||||
|
Pool: "data05",
|
||||||
|
PresentTo: []uint64{
|
||||||
|
27,
|
||||||
|
27,
|
||||||
|
},
|
||||||
|
PurgeAttempts: 0,
|
||||||
|
PurgeTime: 0,
|
||||||
|
RealityDeviceNumber: 0,
|
||||||
|
ReferenceID: "",
|
||||||
|
ResID: "79bd3bd8-3424-48d3-963f-1870d506f169",
|
||||||
|
ResName: "volumes/volume_22637",
|
||||||
|
Role: "",
|
||||||
|
SEPID: 1,
|
||||||
|
Shareable: false,
|
||||||
|
SizeMax: 0,
|
||||||
|
SizeUsed: 0,
|
||||||
|
Snapshots: nil,
|
||||||
|
Status: "CREATED",
|
||||||
|
TechStatus: "ALLOCATED",
|
||||||
|
Type: "B",
|
||||||
|
VMID: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListDisksUnattached_FilterByID(t *testing.T) {
|
||||||
|
actual := unattachedDisks.FilterByID(22636)
|
||||||
|
|
||||||
|
if len(actual) == 0 {
|
||||||
|
t.Fatal("No elements were found")
|
||||||
|
}
|
||||||
|
|
||||||
|
actualItem := actual.FindOne()
|
||||||
|
|
||||||
|
if actualItem.ID != 22636 {
|
||||||
|
t.Fatal("expected ID 22636, found: ", actualItem.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListDisksUnattached_FilterByName(t *testing.T) {
|
||||||
|
actual := unattachedDisks.FilterByName("test_disk")
|
||||||
|
|
||||||
|
if len(actual) != 2 {
|
||||||
|
t.Fatal("expected 2 elements, found: ", len(actual))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range actual {
|
||||||
|
if item.Name != "test_disk" {
|
||||||
|
t.Fatal("expected 'test_disk' name, found: ", item.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListDisksUnattached_FilterByStatus(t *testing.T) {
|
||||||
|
actual := unattachedDisks.FilterByStatus("CREATED")
|
||||||
|
|
||||||
|
if len(actual) == 0 {
|
||||||
|
t.Fatal("No elements were found")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range actual {
|
||||||
|
if item.Status != "CREATED" {
|
||||||
|
t.Fatal("expected 'CREATED' status, found: ", item.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListDisksUnattached_FilterByTechStatus(t *testing.T) {
|
||||||
|
actual := unattachedDisks.FilterByTechStatus("ALLOCATED")
|
||||||
|
|
||||||
|
if len(actual) == 0 {
|
||||||
|
t.Fatal("No elements were found")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range actual {
|
||||||
|
if item.TechStatus != "ALLOCATED" {
|
||||||
|
t.Fatal("expected 'ALLOCATED' techStatus, found: ", item.TechStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListDisksUnattached_FilterFunc(t *testing.T) {
|
||||||
|
actual := unattachedDisks.FilterFunc(func(id ItemDiskUnattached) bool {
|
||||||
|
return len(id.PresentTo) == 2
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual) == 0 {
|
||||||
|
t.Fatal("No elements were found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(actual[0].PresentTo) != 2 {
|
||||||
|
t.Fatal("expected 2 elements in PresentTo, found: ", len(actual[0].PresentTo))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestListDisksUnattached_SortByCreatedTime(t *testing.T) {
|
||||||
|
actual := unattachedDisks.SortByCreatedTime(false)
|
||||||
|
|
||||||
|
if actual[0].ID != 22636 {
|
||||||
|
t.Fatal("expected ID 22636, found: ", actual[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual = unattachedDisks.SortByCreatedTime(true)
|
||||||
|
|
||||||
|
if actual[0].ID != 22637 {
|
||||||
|
t.Fatal("expected ID 22637, found: ", actual[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,31 +3,26 @@ package disks
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get information about disk
|
// Request struct for get information about disk
|
||||||
type GetRequest struct {
|
type GetRequest struct {
|
||||||
// ID of the disk
|
// ID of the disk
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq GetRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets disk details
|
// Get gets disk details
|
||||||
// Notice: the devicename field is the name as it is passed to the kernel (kname in linux) for unattached disks this field has no relevant value
|
// Notice: the devicename field is the name as it is passed to the kernel (kname in linux) for unattached disks this field has no relevant value
|
||||||
func (d Disks) Get(ctx context.Context, req GetRequest) (*RecordDisk, error) {
|
func (d Disks) Get(ctx context.Context, req GetRequest) (*RecordDisk, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/get"
|
url := "/cloudapi/disks/get"
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for limit IO
|
// Request struct for limit IO
|
||||||
type LimitIORequest struct {
|
type LimitIORequest struct {
|
||||||
// ID of the disk to limit
|
// ID of the disk to limit
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// Alias for total_iops_sec for backwards compatibility
|
// Alias for total_iops_sec for backwards compatibility
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -70,21 +71,15 @@ type LimitIORequest struct {
|
|||||||
SizeIOPSSec uint64 `url:"size_iops_sec,omitempty" json:"size_iops_sec,omitempty"`
|
SizeIOPSSec uint64 `url:"size_iops_sec,omitempty" json:"size_iops_sec,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (drq LimitIORequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LimitIO limit IO for a certain disk
|
// LimitIO limit IO for a certain disk
|
||||||
// total and read/write options are not allowed to be combined
|
// total and read/write options are not allowed to be combined
|
||||||
// see http://libvirt.org/formatdomain.html#elementsDisks iotune section for more details
|
// see http://libvirt.org/formatdomain.html#elementsDisks iotune section for more details
|
||||||
func (d Disks) LimitIO(ctx context.Context, req LimitIORequest) (bool, error) {
|
func (d Disks) LimitIO(ctx context.Context, req LimitIORequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/limitIO"
|
url := "/cloudapi/disks/limitIO"
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
// Request struct for get list types of disks
|
// Request struct for get list types of disks
|
||||||
type ListTypesRequest struct {
|
type ListTypesRequest struct {
|
||||||
// Show detailed disk types by seps
|
// Show detailed disk types by seps
|
||||||
// Required: false
|
// Required: true
|
||||||
Detailed bool `url:"detailed" json:"detailed"`
|
Detailed bool `url:"detailed" json:"detailed" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListTypes gets list defined disk types
|
// ListTypes gets list defined disk types
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type ListUnattachedRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ListUnattached gets list of unattached disks
|
// ListUnattached gets list of unattached disks
|
||||||
func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (ListDisks, error) {
|
func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (ListDisksUnattached, error) {
|
||||||
url := "/cloudapi/disks/listUnattached"
|
url := "/cloudapi/disks/listUnattached"
|
||||||
|
|
||||||
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := d.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
@@ -22,7 +22,7 @@ func (d Disks) ListUnattached(ctx context.Context, req ListUnattachedRequest) (L
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
list := ListDisks{}
|
list := ListDisksUnattached{}
|
||||||
|
|
||||||
err = json.Unmarshal(res, &list)
|
err = json.Unmarshal(res, &list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -114,9 +114,146 @@ type ItemDisk struct {
|
|||||||
VMID uint64 `json:"vmid"`
|
VMID uint64 `json:"vmid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ItemDiskUnattached struct {
|
||||||
|
// CKey
|
||||||
|
CKey string `json:"_ckey"`
|
||||||
|
|
||||||
|
// Meta
|
||||||
|
Meta []interface{} `json:"_meta"`
|
||||||
|
|
||||||
|
// Account ID
|
||||||
|
AccountID uint64 `json:"accountId"`
|
||||||
|
|
||||||
|
// Account name
|
||||||
|
AccountName string `json:"accountName"`
|
||||||
|
|
||||||
|
// Access Control List
|
||||||
|
ACL map[string]interface{} `json:"acl"`
|
||||||
|
|
||||||
|
// Boot Partition
|
||||||
|
BootPartition uint64 `json:"bootPartition"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedTime uint64 `json:"createdTime"`
|
||||||
|
|
||||||
|
// Deleted time
|
||||||
|
DeletedTime uint64 `json:"deletedTime"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"desc"`
|
||||||
|
|
||||||
|
// Destruction time
|
||||||
|
DestructionTime uint64 `json:"destructionTime"`
|
||||||
|
|
||||||
|
// Disk path
|
||||||
|
DiskPath string `json:"diskPath"`
|
||||||
|
|
||||||
|
// Grid ID
|
||||||
|
GID uint64 `json:"gid"`
|
||||||
|
|
||||||
|
// GUID
|
||||||
|
GUID uint64 `json:"guid"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID uint64 `json:"id"`
|
||||||
|
|
||||||
|
// Image ID
|
||||||
|
ImageID uint64 `json:"imageId"`
|
||||||
|
|
||||||
|
// Images
|
||||||
|
Images []uint64 `json:"images"`
|
||||||
|
|
||||||
|
// IOTune
|
||||||
|
IOTune IOTune `json:"iotune"`
|
||||||
|
|
||||||
|
// IQN
|
||||||
|
IQN string `json:"iqn"`
|
||||||
|
|
||||||
|
// Login
|
||||||
|
Login string `json:"login"`
|
||||||
|
|
||||||
|
// Milestones
|
||||||
|
Milestones uint64 `json:"milestones"`
|
||||||
|
|
||||||
|
// Name
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Order
|
||||||
|
Order uint64 `json:"order"`
|
||||||
|
|
||||||
|
// Params
|
||||||
|
Params string `json:"params"`
|
||||||
|
|
||||||
|
// Parent ID
|
||||||
|
ParentID uint64 `json:"parentId"`
|
||||||
|
|
||||||
|
// Password
|
||||||
|
Password string `json:"passwd"`
|
||||||
|
|
||||||
|
//PCISlot
|
||||||
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
|
// Pool
|
||||||
|
Pool string `json:"pool"`
|
||||||
|
|
||||||
|
// Present to
|
||||||
|
PresentTo []uint64 `json:"presentTo"`
|
||||||
|
|
||||||
|
// Purge attempts
|
||||||
|
PurgeAttempts uint64 `json:"purgeAttempts"`
|
||||||
|
|
||||||
|
// Purge time
|
||||||
|
PurgeTime uint64 `json:"purgeTime"`
|
||||||
|
|
||||||
|
// Reality device number
|
||||||
|
RealityDeviceNumber uint64 `json:"realityDeviceNumber"`
|
||||||
|
|
||||||
|
// Reference ID
|
||||||
|
ReferenceID string `json:"referenceId"`
|
||||||
|
|
||||||
|
// Resource ID
|
||||||
|
ResID string `json:"resId"`
|
||||||
|
|
||||||
|
// Resource name
|
||||||
|
ResName string `json:"resName"`
|
||||||
|
|
||||||
|
// Role
|
||||||
|
Role string `json:"role"`
|
||||||
|
|
||||||
|
// ID SEP
|
||||||
|
SEPID uint64 `json:"sepId"`
|
||||||
|
|
||||||
|
// Shareable
|
||||||
|
Shareable bool `json:"shareable"`
|
||||||
|
|
||||||
|
// Size max
|
||||||
|
SizeMax uint64 `json:"sizeMax"`
|
||||||
|
|
||||||
|
// Size used
|
||||||
|
SizeUsed float64 `json:"sizeUsed"`
|
||||||
|
|
||||||
|
// List of snapshots
|
||||||
|
Snapshots ListSnapshots `json:"snapshots"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Tech status
|
||||||
|
TechStatus string `json:"techStatus"`
|
||||||
|
|
||||||
|
// Type
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Virtual machine ID
|
||||||
|
VMID uint64 `json:"vmid"`
|
||||||
|
}
|
||||||
|
|
||||||
// List of disks
|
// List of disks
|
||||||
type ListDisks []ItemDisk
|
type ListDisks []ItemDisk
|
||||||
|
|
||||||
|
// List of unattached disks
|
||||||
|
type ListDisksUnattached []ItemDiskUnattached
|
||||||
|
|
||||||
// Main information about snapshot
|
// Main information about snapshot
|
||||||
type ItemSnapshot struct {
|
type ItemSnapshot struct {
|
||||||
// GUID
|
// GUID
|
||||||
@@ -240,7 +377,7 @@ type RecordDisk struct {
|
|||||||
ParentID uint64 `json:"parentId"`
|
ParentID uint64 `json:"parentId"`
|
||||||
|
|
||||||
// PCI slot
|
// PCI slot
|
||||||
PCISlot uint64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
// Pool
|
// Pool
|
||||||
Pool string `json:"pool"`
|
Pool string `json:"pool"`
|
||||||
|
|||||||
@@ -2,38 +2,30 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for rename disk
|
// Request struct for rename disk
|
||||||
type RenameRequest struct {
|
type RenameRequest struct {
|
||||||
// ID of the disk to rename
|
// ID of the disk to rename
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// New name of disk
|
// New name of disk
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq RenameRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if drq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename rename disk
|
// Rename rename disk
|
||||||
func (d Disks) Rename(ctx context.Context, req RenameRequest) (bool, error) {
|
func (d Disks) Rename(ctx context.Context, req RenameRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/rename"
|
url := "/cloudapi/disks/rename"
|
||||||
|
|||||||
@@ -2,31 +2,21 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for resize disk
|
// Request struct for resize disk
|
||||||
type ResizeRequest struct {
|
type ResizeRequest struct {
|
||||||
// ID of the disk to resize
|
// ID of the disk to resize
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// New size of the disk in GB
|
// New size of the disk in GB
|
||||||
// Required: true
|
// Required: true
|
||||||
Size uint64 `url:"size" json:"size"`
|
Size uint64 `url:"size" json:"size" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq ResizeRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if drq.Size == 0 {
|
|
||||||
return errors.New("validation-error: field Size can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize resize disk
|
// Resize resize disk
|
||||||
@@ -34,9 +24,11 @@ func (drq ResizeRequest) validate() error {
|
|||||||
// in that case please stop and start your machine after changing the disk size, for your changes to be reflected.
|
// in that case please stop and start your machine after changing the disk size, for your changes to be reflected.
|
||||||
// This method will not be used for disks, assigned to computes. Only unassigned disks and disks, assigned with "old" virtual machines.
|
// This method will not be used for disks, assigned to computes. Only unassigned disks and disks, assigned with "old" virtual machines.
|
||||||
func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) {
|
func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/resize"
|
url := "/cloudapi/disks/resize"
|
||||||
@@ -59,9 +51,11 @@ func (d Disks) Resize(ctx context.Context, req ResizeRequest) (bool, error) {
|
|||||||
// in that case please stop and start your machine after changing the disk size, for your changes to be reflected.
|
// in that case please stop and start your machine after changing the disk size, for your changes to be reflected.
|
||||||
// This method will not be used for disks, assigned to "old" virtual machines. Only unassigned disks and disks, assigned with computes.
|
// This method will not be used for disks, assigned to "old" virtual machines. Only unassigned disks and disks, assigned with computes.
|
||||||
func (d Disks) Resize2(ctx context.Context, req ResizeRequest) (bool, error) {
|
func (d Disks) Resize2(ctx context.Context, req ResizeRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/resize2"
|
url := "/cloudapi/disks/resize2"
|
||||||
|
|||||||
@@ -2,38 +2,30 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for restore a deleted unattached disk
|
// Request struct for restore a deleted unattached disk
|
||||||
type RestoreRequest struct {
|
type RestoreRequest struct {
|
||||||
// ID of the disk to restore
|
// ID of the disk to restore
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// Reason for restoring the disk
|
// Reason for restoring the disk
|
||||||
// Required: true
|
// Required: true
|
||||||
Reason string `url:"reason" json:"reason"`
|
Reason string `url:"reason" json:"reason" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq RestoreRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if drq.Reason == "" {
|
|
||||||
return errors.New("validation-error: field Reason can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restore a deleted unattached disk from recycle bin
|
// Restore restore a deleted unattached disk from recycle bin
|
||||||
func (d Disks) Restore(ctx context.Context, req RestoreRequest) (bool, error) {
|
func (d Disks) Restore(ctx context.Context, req RestoreRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/restore"
|
url := "/cloudapi/disks/restore"
|
||||||
|
|||||||
@@ -41,3 +41,39 @@ func (idisk ItemDisk) Serialize(params ...string) (serialization.Serialized, err
|
|||||||
|
|
||||||
return json.Marshal(idisk)
|
return json.Marshal(idisk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serialize returns JSON-serialized []byte. Used as a wrapper over json.Marshal and json.MarshalIndent functions.
|
||||||
|
//
|
||||||
|
// In order to serialize with indent make sure to follow these guidelines:
|
||||||
|
// - First argument -> prefix
|
||||||
|
// - Second argument -> indent
|
||||||
|
func (lu ListDisksUnattached) Serialize(params ...string) (serialization.Serialized, error) {
|
||||||
|
if len(lu) == 0 {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params) > 1 {
|
||||||
|
prefix := params[0]
|
||||||
|
indent := params[1]
|
||||||
|
|
||||||
|
return json.MarshalIndent(lu, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(lu)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serialize returns JSON-serialized []byte. Used as a wrapper over json.Marshal and json.MarshalIndent functions.
|
||||||
|
//
|
||||||
|
// In order to serialize with indent make sure to follow these guidelines:
|
||||||
|
// - First argument -> prefix
|
||||||
|
// - Second argument -> indent
|
||||||
|
func (idisk ItemDiskUnattached) Serialize(params ...string) (serialization.Serialized, error) {
|
||||||
|
if len(params) > 1 {
|
||||||
|
prefix := params[0]
|
||||||
|
indent := params[1]
|
||||||
|
|
||||||
|
return json.MarshalIndent(idisk, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(idisk)
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for share data disk
|
// Request struct for share data disk
|
||||||
type ShareRequest struct {
|
type ShareRequest struct {
|
||||||
// ID of the disk to share
|
// ID of the disk to share
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq ShareRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Share shares data disk
|
// Share shares data disk
|
||||||
func (d Disks) Share(ctx context.Context, req ShareRequest) (bool, error) {
|
func (d Disks) Share(ctx context.Context, req ShareRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/share"
|
url := "/cloudapi/disks/share"
|
||||||
|
|||||||
@@ -2,39 +2,30 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete snapshot
|
// Request struct for delete snapshot
|
||||||
type SnapshotDeleteRequest struct {
|
type SnapshotDeleteRequest struct {
|
||||||
// ID of disk to delete
|
// ID of disk to delete
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// Label of the snapshot to delete
|
// Label of the snapshot to delete
|
||||||
// Required: false
|
// Required: true
|
||||||
Label string `url:"label" json:"label"`
|
Label string `url:"label" json:"label" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq SnapshotDeleteRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
if drq.Label == "" {
|
|
||||||
return errors.New("validation-error: field Label can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SnapshotDelete deletes a snapshot
|
// SnapshotDelete deletes a snapshot
|
||||||
func (d Disks) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) {
|
func (d Disks) SnapshotDelete(ctx context.Context, req SnapshotDeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/snapshotDelete"
|
url := "/cloudapi/disks/snapshotDelete"
|
||||||
|
|||||||
@@ -2,42 +2,34 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for rollback snapshot
|
// Request struct for rollback snapshot
|
||||||
type SnapshotRollbackRequest struct {
|
type SnapshotRollbackRequest struct {
|
||||||
// ID of the disk
|
// ID of the disk
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
|
|
||||||
// Label of the snapshot to rollback
|
// Label of the snapshot to rollback
|
||||||
// Required: true
|
// Required: false
|
||||||
Label string `url:"label" json:"label"`
|
Label string `url:"label,omitempty" json:"label,omitempty"`
|
||||||
|
|
||||||
// Timestamp of the snapshot to rollback
|
// Timestamp of the snapshot to rollback
|
||||||
// Required: true
|
// Required: false
|
||||||
TimeStamp uint64 `url:"timestamp" json:"timestamp"`
|
TimeStamp uint64 `url:"timestamp,omitempty" json:"timestamp,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq SnapshotRollbackRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if drq.Label == "" && drq.TimeStamp == 0 {
|
|
||||||
return errors.New("validation-error: field Label or field TimeStamp can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SnapshotRollback rollback an individual disk snapshot
|
// SnapshotRollback rollback an individual disk snapshot
|
||||||
func (d Disks) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) {
|
func (d Disks) SnapshotRollback(ctx context.Context, req SnapshotRollbackRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/snapshotRollback"
|
url := "/cloudapi/disks/snapshotRollback"
|
||||||
|
|||||||
@@ -58,3 +58,60 @@ func (ld ListDisks) SortByDeletedTime(inverse bool) ListDisks {
|
|||||||
|
|
||||||
return ld
|
return ld
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SortByCreatedTime sorts ListDisksUnattached by the CreatedTime field in ascending order.
|
||||||
|
//
|
||||||
|
// If inverse param is set to true, the order is reversed.
|
||||||
|
func (lu ListDisksUnattached) SortByCreatedTime(inverse bool) ListDisksUnattached {
|
||||||
|
if len(lu) < 2 {
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(lu, func(i, j int) bool {
|
||||||
|
if inverse {
|
||||||
|
return lu[i].CreatedTime > lu[j].CreatedTime
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu[i].CreatedTime < lu[j].CreatedTime
|
||||||
|
})
|
||||||
|
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortByDestructionTime sorts ListDisksUnattached by the DestructionTime field in ascending order.
|
||||||
|
//
|
||||||
|
// If inverse param is set to true, the order is reversed.
|
||||||
|
func (lu ListDisksUnattached) SortByDestructionTime(inverse bool) ListDisksUnattached {
|
||||||
|
if len(lu) < 2 {
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(lu, func(i, j int) bool {
|
||||||
|
if inverse {
|
||||||
|
return lu[i].DestructionTime > lu[j].DestructionTime
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu[i].DestructionTime < lu[j].DestructionTime
|
||||||
|
})
|
||||||
|
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortByDeletedTime sorts ListDisksUnattached by the DeletedTime field in ascending order.
|
||||||
|
//
|
||||||
|
// If inverse param is set to true, the order is reversed.
|
||||||
|
func (lu ListDisksUnattached) SortByDeletedTime(inverse bool) ListDisksUnattached {
|
||||||
|
if len(lu) < 2 {
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(lu, func(i, j int) bool {
|
||||||
|
if inverse {
|
||||||
|
return lu[i].DeletedTime > lu[j].DeletedTime
|
||||||
|
}
|
||||||
|
|
||||||
|
return lu[i].DeletedTime < lu[j].DeletedTime
|
||||||
|
})
|
||||||
|
|
||||||
|
return lu
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package disks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for unshare data disk
|
// Request struct for unshare data disk
|
||||||
type UnshareRequest struct {
|
type UnshareRequest struct {
|
||||||
// ID of the disk to unshare
|
// ID of the disk to unshare
|
||||||
// Required: true
|
// Required: true
|
||||||
DiskID uint64 `url:"diskId" json:"diskId"`
|
DiskID uint64 `url:"diskId" json:"diskId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (drq UnshareRequest) validate() error {
|
|
||||||
if drq.DiskID == 0 {
|
|
||||||
return errors.New("validation-error: field DiskID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unshare unshares data disk
|
// Unshare unshares data disk
|
||||||
func (d Disks) Unshare(ctx context.Context, req UnshareRequest) (bool, error) {
|
func (d Disks) Unshare(ctx context.Context, req UnshareRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/disks/unshare"
|
url := "/cloudapi/disks/unshare"
|
||||||
|
|||||||
@@ -3,30 +3,25 @@ package extnet
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get detailed information about external network
|
// Request struct for get detailed information about external network
|
||||||
type GetRequest struct {
|
type GetRequest struct {
|
||||||
// ID of external network
|
// ID of external network
|
||||||
// Required: true
|
// Required: true
|
||||||
NetID uint64 `url:"net_id" json:"net_id"`
|
NetID uint64 `url:"net_id" json:"net_id" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (erq GetRequest) validate() error {
|
|
||||||
if erq.NetID == 0 {
|
|
||||||
return errors.New("validation-error: field NetID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets detailed information about external network
|
// Get gets detailed information about external network
|
||||||
func (e ExtNet) Get(ctx context.Context, req GetRequest) (*RecordExtNet, error) {
|
func (e ExtNet) Get(ctx context.Context, req GetRequest) (*RecordExtNet, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/extnet/get"
|
url := "/cloudapi/extnet/get"
|
||||||
|
|||||||
@@ -3,30 +3,25 @@ package extnet
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get list computes
|
// Request struct for get list computes
|
||||||
type ListComputesRequest struct {
|
type ListComputesRequest struct {
|
||||||
// Filter by account ID
|
// Filter by account ID
|
||||||
// Required: true
|
// Required: true
|
||||||
AccountID uint64 `url:"accountId" json:"accountId"`
|
AccountID uint64 `url:"accountId" json:"accountId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (erq ListComputesRequest) validate() error {
|
|
||||||
if erq.AccountID == 0 {
|
|
||||||
return errors.New("validation-error: field AccountID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListComputes gets computes from account with extnets
|
// ListComputes gets computes from account with extnets
|
||||||
func (e ExtNet) ListComputes(ctx context.Context, req ListComputesRequest) (ListExtNetComputes, error) {
|
func (e ExtNet) ListComputes(ctx context.Context, req ListComputesRequest) (ListExtNetComputes, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/extnet/listComputes"
|
url := "/cloudapi/extnet/listComputes"
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ type ListExtNetComputes []ItemExtNetCompute
|
|||||||
|
|
||||||
// QOS
|
// QOS
|
||||||
type QOS struct {
|
type QOS struct {
|
||||||
|
// EBurst
|
||||||
|
EBurst uint64 `json:"eBurst"`
|
||||||
|
|
||||||
// ERate
|
// ERate
|
||||||
ERate uint64 `json:"eRate"`
|
ERate uint64 `json:"eRate"`
|
||||||
|
|
||||||
@@ -107,6 +110,23 @@ type VNFs struct {
|
|||||||
DHCP uint64 `json:"dhcp"`
|
DHCP uint64 `json:"dhcp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Excluded struct {
|
||||||
|
// ClientType
|
||||||
|
ClientType string `json:"clientType"`
|
||||||
|
|
||||||
|
// IP
|
||||||
|
IP string `json:"ip"`
|
||||||
|
|
||||||
|
// MAC
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// Type
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// VMID
|
||||||
|
VMID uint64 `json:"vmId"`
|
||||||
|
}
|
||||||
|
|
||||||
// Detailed information about external network
|
// Detailed information about external network
|
||||||
type RecordExtNet struct {
|
type RecordExtNet struct {
|
||||||
// CKey
|
// CKey
|
||||||
@@ -134,7 +154,7 @@ type RecordExtNet struct {
|
|||||||
DNS []string `json:"dns"`
|
DNS []string `json:"dns"`
|
||||||
|
|
||||||
// Excluded
|
// Excluded
|
||||||
Excluded []string `json:"excluded"`
|
Excluded []Excluded `json:"excluded"`
|
||||||
|
|
||||||
// Free IPs
|
// Free IPs
|
||||||
FreeIPs uint64 `json:"free_ips"`
|
FreeIPs uint64 `json:"free_ips"`
|
||||||
|
|||||||
@@ -2,38 +2,30 @@ package flipgroup
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for add compute instance
|
// Request struct for add compute instance
|
||||||
type ComputeAddRequest struct {
|
type ComputeAddRequest struct {
|
||||||
// ID of the Floating IP group to add compute instance to
|
// ID of the Floating IP group to add compute instance to
|
||||||
// Required: true
|
// Required: true
|
||||||
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId"`
|
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId" validate:"required"`
|
||||||
|
|
||||||
// ID of the compute instance to add to this group
|
// ID of the compute instance to add to this group
|
||||||
// Required: true
|
// Required: true
|
||||||
ComputeID uint64 `url:"computeId" json:"computeId"`
|
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (frq ComputeAddRequest) validate() error {
|
|
||||||
if frq.FLIPGroupID == 0 {
|
|
||||||
return errors.New("field FLIPGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if frq.ComputeID == 0 {
|
|
||||||
return errors.New("field ComputeID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComputeAdd add compute instance to the Floating IP group
|
// ComputeAdd add compute instance to the Floating IP group
|
||||||
func (f FLIPGroup) ComputeAdd(ctx context.Context, req ComputeAddRequest) (bool, error) {
|
func (f FLIPGroup) ComputeAdd(ctx context.Context, req ComputeAddRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/flipgroup/computeAdd"
|
url := "/cloudapi/flipgroup/computeAdd"
|
||||||
|
|||||||
@@ -2,38 +2,30 @@ package flipgroup
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for remove compute instance
|
// Request struct for remove compute instance
|
||||||
type ComputeRemoveRequest struct {
|
type ComputeRemoveRequest struct {
|
||||||
// ID of the Floating IP group to remove compute instance from
|
// ID of the Floating IP group to remove compute instance from
|
||||||
// Required: true
|
// Required: true
|
||||||
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId"`
|
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId" validate:"required"`
|
||||||
|
|
||||||
// ID of the compute instance to remove
|
// ID of the compute instance to remove
|
||||||
// Required: true
|
// Required: true
|
||||||
ComputeID uint64 `url:"computeId" json:"computeId"`
|
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (frq ComputeRemoveRequest) validate() error {
|
|
||||||
if frq.FLIPGroupID == 0 {
|
|
||||||
return errors.New("field FLIPGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if frq.ComputeID == 0 {
|
|
||||||
return errors.New("field ComputeID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ComputeRemove remove compute instance from the Floating IP group
|
// ComputeRemove remove compute instance from the Floating IP group
|
||||||
func (f FLIPGroup) ComputeRemove(ctx context.Context, req ComputeRemoveRequest) (bool, error) {
|
func (f FLIPGroup) ComputeRemove(ctx context.Context, req ComputeRemoveRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/flipgroup/computeRemove"
|
url := "/cloudapi/flipgroup/computeRemove"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package flipgroup
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
@@ -13,28 +12,28 @@ import (
|
|||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
// Account ID
|
// Account ID
|
||||||
// Required: true
|
// Required: true
|
||||||
AccountID uint64 `url:"accountId" json:"accountId"`
|
AccountID uint64 `url:"accountId" json:"accountId" validate:"required"`
|
||||||
|
|
||||||
// FLIPGroup name
|
// FLIPGroup name
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Network type
|
// Network type
|
||||||
// Should be one of:
|
// Should be one of:
|
||||||
// - EXTNET
|
// - EXTNET
|
||||||
// - VINS
|
// - VINS
|
||||||
// Required: true
|
// Required: true
|
||||||
NetType string `url:"netType" json:"netType"`
|
NetType string `url:"netType" json:"netType" validate:"computeNetType"`
|
||||||
|
|
||||||
// ID of external network or VINS
|
// ID of external network or VINS
|
||||||
// Required: true
|
// Required: true
|
||||||
NetID uint64 `url:"netId" json:"netId"`
|
NetID uint64 `url:"netId" json:"netId" validate:"required"`
|
||||||
|
|
||||||
// Type of client
|
// Type of client
|
||||||
// - 'compute'
|
// - 'compute'
|
||||||
// - 'vins' (will be later)
|
// - 'vins' (will be later)
|
||||||
// Required: true
|
// Required: true
|
||||||
ClientType string `url:"clientType" json:"clientType"`
|
ClientType string `url:"clientType" json:"clientType" validate:"flipgroupClientType"`
|
||||||
|
|
||||||
// IP address to associate with this group. If empty, the platform will autoselect IP address
|
// IP address to associate with this group. If empty, the platform will autoselect IP address
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -45,33 +44,13 @@ type CreateRequest struct {
|
|||||||
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (frq CreateRequest) validate() error {
|
|
||||||
if frq.AccountID == 0 {
|
|
||||||
return errors.New("field AccountID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if frq.NetID == 0 {
|
|
||||||
return errors.New("field NetID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if frq.Name == "" {
|
|
||||||
return errors.New("field Name can not be empty")
|
|
||||||
}
|
|
||||||
validator := validators.StringInSlice(frq.NetType, []string{"EXTNET", "VINS"})
|
|
||||||
if !validator {
|
|
||||||
return errors.New("field Name can be only EXTNET or VINS")
|
|
||||||
}
|
|
||||||
validator = validators.StringInSlice(frq.ClientType, []string{"compute", "node"})
|
|
||||||
if !validator {
|
|
||||||
return errors.New("field Name can be only compute or node")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create method will create a new FLIPGorup in the specified Account
|
// Create method will create a new FLIPGorup in the specified Account
|
||||||
func (f FLIPGroup) Create(ctx context.Context, req CreateRequest) (*RecordFLIPGroup, error) {
|
func (f FLIPGroup) Create(ctx context.Context, req CreateRequest) (*RecordFLIPGroup, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/flipgroup/create"
|
url := "/cloudapi/flipgroup/create"
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package flipgroup
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete FLIPGroup
|
// Request struct for delete FLIPGroup
|
||||||
type DeleteRequest struct {
|
type DeleteRequest struct {
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
// Required: true
|
// Required: true
|
||||||
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId"`
|
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (frq DeleteRequest) validate() error {
|
|
||||||
if frq.FLIPGroupID == 0 {
|
|
||||||
return errors.New("field FLIPGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete method wil delete Floating IP group
|
// Delete method wil delete Floating IP group
|
||||||
func (f FLIPGroup) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
func (f FLIPGroup) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/flipgroup/delete"
|
url := "/cloudapi/flipgroup/delete"
|
||||||
|
|||||||
@@ -2,39 +2,34 @@ package flipgroup
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for edit FLIPGroup
|
// Request struct for edit FLIPGroup
|
||||||
type EditRequest struct {
|
type EditRequest struct {
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
// Required: true
|
// Required: true
|
||||||
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId"`
|
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId" validate:"required"`
|
||||||
|
|
||||||
// FLIPGroup name
|
// FLIPGroup name
|
||||||
// Required: true
|
// Required: false
|
||||||
Name string `url:"name,omitempty" json:"name,omitempty"`
|
Name string `url:"name,omitempty" json:"name,omitempty"`
|
||||||
|
|
||||||
// FLIPGroup description
|
// FLIPGroup description
|
||||||
// Required: true
|
// Required: false
|
||||||
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (frq EditRequest) validate() error {
|
|
||||||
if frq.FLIPGroupID == 0 {
|
|
||||||
return errors.New("field FLIPGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Edit edits FLIPGroup fields
|
// Edit edits FLIPGroup fields
|
||||||
func (f FLIPGroup) Edit(ctx context.Context, req EditRequest) (bool, error) {
|
func (f FLIPGroup) Edit(ctx context.Context, req EditRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/flipgroup/edit"
|
url := "/cloudapi/flipgroup/edit"
|
||||||
|
|||||||
@@ -3,30 +3,25 @@ package flipgroup
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get information about FLIPGroup
|
// Request struct for get information about FLIPGroup
|
||||||
type GetRequest struct {
|
type GetRequest struct {
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
// Required: true
|
// Required: true
|
||||||
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId"`
|
FLIPGroupID uint64 `url:"flipgroupId" json:"flipgroupId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (frq GetRequest) validate() error {
|
|
||||||
if frq.FLIPGroupID == 0 {
|
|
||||||
return errors.New("field FLIPGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets details of the specified Floating IP group
|
// Get gets details of the specified Floating IP group
|
||||||
func (f FLIPGroup) Get(ctx context.Context, req GetRequest) (*ItemFLIPGroup, error) {
|
func (f FLIPGroup) Get(ctx context.Context, req GetRequest) (*ItemFLIPGroup, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/flipgroup/get"
|
url := "/cloudapi/flipgroup/get"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type CreateRequest struct {
|
|||||||
|
|
||||||
// Boot type of image bios or UEFI
|
// Boot type of image bios or UEFI
|
||||||
// Required: true
|
// Required: true
|
||||||
BootType string `url:"boottype" json:"boottype" validate:"required,bootType"`
|
BootType string `url:"boottype" json:"boottype" validate:"required,imageBootType"`
|
||||||
|
|
||||||
// Image type
|
// Image type
|
||||||
// Should be:
|
// Should be:
|
||||||
|
|||||||
@@ -3,29 +3,25 @@ package k8ci
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get information about K8CI
|
// Request struct for get information about K8CI
|
||||||
type GetRequest struct {
|
type GetRequest struct {
|
||||||
// ID of the K8 catalog item to get
|
// ID of the K8 catalog item to get
|
||||||
// Required: true
|
// Required: true
|
||||||
K8CIID uint64 `url:"k8ciId" json:"k8ciId"`
|
K8CIID uint64 `url:"k8ciId" json:"k8ciId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq GetRequest) validate() error {
|
|
||||||
if krq.K8CIID == 0 {
|
|
||||||
return errors.New("field K8CIID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets details of the specified K8 catalog item
|
// Get gets details of the specified K8 catalog item
|
||||||
func (k K8CI) Get(ctx context.Context, req GetRequest) (*RecordK8CI, error) {
|
func (k K8CI) Get(ctx context.Context, req GetRequest) (*RecordK8CI, error) {
|
||||||
if err := req.validate(); err != nil {
|
err := validators.ValidateRequest(req)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8ci/get"
|
url := "/cloudapi/k8ci/get"
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ type RecordK8CI struct {
|
|||||||
// Name
|
// Name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Network plugins
|
||||||
|
NetworkPlugins []string `json:"networkPlugins"`
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,28 +2,34 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for create kubernetes cluster
|
// Request struct for create kubernetes cluster
|
||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
// Name of Kubernetes cluster
|
// Name of Kubernetes cluster
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Resource Group ID for cluster placement
|
// Resource Group ID for cluster placement
|
||||||
// Required: true
|
// Required: true
|
||||||
RGID uint64 `url:"rgId" json:"rgId"`
|
RGID uint64 `url:"rgId" json:"rgId" validate:"required"`
|
||||||
|
|
||||||
// ID of Kubernetes catalog item (k8sci) for cluster
|
// ID of Kubernetes catalog item (k8sci) for cluster
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SCIID uint64 `url:"k8ciId" json:"k8ciId"`
|
K8SCIID uint64 `url:"k8ciId" json:"k8ciId" validate:"required"`
|
||||||
|
|
||||||
// Name for first worker group created with cluster
|
// Name for first worker group created with cluster
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkerGroupName string `url:"workerGroupName" json:"workerGroupName"`
|
WorkerGroupName string `url:"workerGroupName" json:"workerGroupName" validate:"required"`
|
||||||
|
|
||||||
|
// Network plugin
|
||||||
|
// Must be one of these values: flannel, weawenet, calico
|
||||||
|
// Required: true
|
||||||
|
NetworkPlugin string `url:"networkPlugin" json:"networkPlugin" validate:"required,networkPlugin"`
|
||||||
|
|
||||||
// ID of SEP to create boot disks for master nodes. Uses images SEP ID if not set
|
// ID of SEP to create boot disks for master nodes. Uses images SEP ID if not set
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -95,35 +101,20 @@ type CreateRequest struct {
|
|||||||
// Create Kubernetes cluster with masters nodes behind load balancer if true.
|
// Create Kubernetes cluster with masters nodes behind load balancer if true.
|
||||||
// Otherwise give all cluster nodes direct external addresses from selected ExtNet
|
// Otherwise give all cluster nodes direct external addresses from selected ExtNet
|
||||||
// Required: false
|
// Required: false
|
||||||
WithLB bool `url:"withLB,omitempty" json:"withLB,omitempty"`
|
WithLB bool `url:"withLB" json:"withLB"`
|
||||||
|
|
||||||
// Text description of this Kubernetes cluster
|
// Text description of this Kubernetes cluster
|
||||||
// Required: false
|
// Required: false
|
||||||
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq CreateRequest) validate() error {
|
|
||||||
if krq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
if krq.RGID == 0 {
|
|
||||||
return errors.New("validation-error: field RGID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.K8SCIID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SCIID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkerGroupName == "" {
|
|
||||||
return errors.New("validation-error: field WorkerGroupName can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates a new Kubernetes cluster in the specified Resource Group
|
// Create creates a new Kubernetes cluster in the specified Resource Group
|
||||||
func (k8s K8S) Create(ctx context.Context, req CreateRequest) (string, error) {
|
func (k8s K8S) Create(ctx context.Context, req CreateRequest) (string, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return "", validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/create"
|
url := "/cloudapi/k8s/create"
|
||||||
|
|||||||
@@ -2,36 +2,31 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete kubernetes cluster
|
// Request struct for delete kubernetes cluster
|
||||||
type DeleteRequest struct {
|
type DeleteRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// True if cluster is destroyed permanently.
|
// True if cluster is destroyed permanently.
|
||||||
// Otherwise it can be restored from Recycle Bin
|
// Otherwise it can be restored from Recycle Bin
|
||||||
// Required: true
|
// Required: true
|
||||||
Permanently bool `url:"permanently" json:"permanently"`
|
Permanently bool `url:"permanently" json:"permanently" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq DeleteRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes kubernetes cluster
|
// Delete deletes kubernetes cluster
|
||||||
func (k8s K8S) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
func (k8s K8S) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/delete"
|
url := "/cloudapi/k8s/delete"
|
||||||
|
|||||||
@@ -2,45 +2,34 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete master from group
|
// Request struct for delete master from group
|
||||||
type DeleteMasterFromGroupRequest struct {
|
type DeleteMasterFromGroupRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// ID of the masters compute group
|
// ID of the masters compute group
|
||||||
// Required: true
|
// Required: true
|
||||||
MasterGroupID uint64 `url:"masterGroupId" json:"masterGroupId"`
|
MasterGroupID uint64 `url:"masterGroupId" json:"masterGroupId" validate:"required"`
|
||||||
|
|
||||||
// List of Compute IDs of master nodes to delete
|
// List of Compute IDs of master nodes to delete
|
||||||
// Required: true
|
// Required: true
|
||||||
MasterIDs []string `url:"masterIds" json:"masterIds"`
|
MasterIDs []string `url:"masterIds" json:"masterIds" validate:"min=1"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq DeleteMasterFromGroupRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.MasterGroupID == 0 {
|
|
||||||
return errors.New("validation-error: field MasterGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if len(krq.MasterIDs) == 0 {
|
|
||||||
return errors.New("validation-error: field MasterIDs can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteMasterFromGroup deletes compute from masters group in selected Kubernetes cluster
|
// DeleteMasterFromGroup deletes compute from masters group in selected Kubernetes cluster
|
||||||
func (k8s K8S) DeleteMasterFromGroup(ctx context.Context, req DeleteMasterFromGroupRequest) (bool, error) {
|
func (k8s K8S) DeleteMasterFromGroup(ctx context.Context, req DeleteMasterFromGroupRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/deleteMasterFromGroup"
|
url := "/cloudapi/k8s/deleteMasterFromGroup"
|
||||||
|
|||||||
@@ -2,45 +2,34 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete worker from group
|
// Request struct for delete worker from group
|
||||||
type DeleteWorkerFromGroupRequest struct {
|
type DeleteWorkerFromGroupRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// ID of the workers compute group
|
// ID of the workers compute group
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId"`
|
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"`
|
||||||
|
|
||||||
// Compute ID of worker node to delete
|
// Compute ID of worker node to delete
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkerID uint64 `url:"workerId" json:"workerId"`
|
WorkerID uint64 `url:"workerId" json:"workerId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq DeleteWorkerFromGroupRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkersGroupID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkerID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkerID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteWorkerFromGroup deletes worker compute from workers group in selected Kubernetes cluster
|
// DeleteWorkerFromGroup deletes worker compute from workers group in selected Kubernetes cluster
|
||||||
func (k8s K8S) DeleteWorkerFromGroup(ctx context.Context, req DeleteWorkerFromGroupRequest) (bool, error) {
|
func (k8s K8S) DeleteWorkerFromGroup(ctx context.Context, req DeleteWorkerFromGroupRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/deleteWorkerFromGroup"
|
url := "/cloudapi/k8s/deleteWorkerFromGroup"
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for disable/enable kubernetes cluster
|
// Request struct for disable/enable kubernetes cluster
|
||||||
type DisabelEnableRequest struct {
|
type DisableEnableRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq DisabelEnableRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable disables kubernetes cluster by ID
|
// Disable disables kubernetes cluster by ID
|
||||||
func (k8s K8S) Disable(ctx context.Context, req DisabelEnableRequest) (bool, error) {
|
func (k8s K8S) Disable(ctx context.Context, req DisableEnableRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/disable"
|
url := "/cloudapi/k8s/disable"
|
||||||
@@ -45,10 +40,12 @@ func (k8s K8S) Disable(ctx context.Context, req DisabelEnableRequest) (bool, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enable enables kubernetes cluster by ID
|
// Enable enables kubernetes cluster by ID
|
||||||
func (k8s K8S) Enable(ctx context.Context, req DisabelEnableRequest) (bool, error) {
|
func (k8s K8S) Enable(ctx context.Context, req DisableEnableRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/enable"
|
url := "/cloudapi/k8s/enable"
|
||||||
|
|||||||
@@ -3,42 +3,34 @@ package k8s
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get information about group of kubernetes cluster
|
// Request struct for get information about group of kubernetes cluster
|
||||||
type FindGroupByLabelRequest struct {
|
type FindGroupByLabelRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// List of labels to search
|
// List of labels to search
|
||||||
// Required: true
|
// Required: true
|
||||||
Labels []string `url:"labels" json:"labels"`
|
Labels []string `url:"labels" json:"labels" validate:"min=1"`
|
||||||
|
|
||||||
// If true and more than one label provided, select only groups that have all provided labels.
|
// If true and more than one label provided, select only groups that have all provided labels.
|
||||||
// If false - groups that have at least one label
|
// If false - groups that have at least one label
|
||||||
// Required: true
|
// Required: false
|
||||||
Strict bool `url:"strict" json:"strict"`
|
Strict bool `url:"strict,omitempty" json:"strict,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq FindGroupByLabelRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if len(krq.Labels) == 0 {
|
|
||||||
return errors.New("validation-error: field Labels can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindGroupByLabel find worker group information by one on more labels
|
// FindGroupByLabel find worker group information by one on more labels
|
||||||
func (k8s K8S) FindGroupByLabel(ctx context.Context, req FindGroupByLabelRequest) (ListK8SGroups, error) {
|
func (k8s K8S) FindGroupByLabel(ctx context.Context, req FindGroupByLabelRequest) (ListK8SGroups, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/findGroupByLabel"
|
url := "/cloudapi/k8s/findGroupByLabel"
|
||||||
|
|||||||
@@ -3,30 +3,25 @@ package k8s
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get detailed information about kubernetes cluster
|
// Request struct for get detailed information about kubernetes cluster
|
||||||
type GetRequest struct {
|
type GetRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq GetRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gets information about Kubernetes cluster
|
// Get gets information about Kubernetes cluster
|
||||||
func (k8s K8S) Get(ctx context.Context, req GetRequest) (*RecordK8S, error) {
|
func (k8s K8S) Get(ctx context.Context, req GetRequest) (*RecordK8S, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/get"
|
url := "/cloudapi/k8s/get"
|
||||||
|
|||||||
@@ -2,30 +2,25 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get configuration of kubernetes cluster
|
// Request struct for get configuration of kubernetes cluster
|
||||||
type GetConfigRequest struct {
|
type GetConfigRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq GetConfigRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig gets configuration data to access Kubernetes cluster
|
// GetConfig gets configuration data to access Kubernetes cluster
|
||||||
func (k8s K8S) GetConfig(ctx context.Context, req GetConfigRequest) (string, error) {
|
func (k8s K8S) GetConfig(ctx context.Context, req GetConfigRequest) (string, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return "", validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/getConfig"
|
url := "/cloudapi/k8s/getConfig"
|
||||||
|
|||||||
@@ -2,37 +2,29 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get node annotations
|
// Request struct for get node annotations
|
||||||
type GetNodeAnnotationsRequest struct {
|
type GetNodeAnnotationsRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// Node ID
|
// Node ID
|
||||||
// Required: true
|
// Required: true
|
||||||
NodeID uint64 `url:"nodeId" json:"nodeId"`
|
NodeID uint64 `url:"nodeId" json:"nodeId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq GetNodeAnnotationsRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.NodeID == 0 {
|
|
||||||
return errors.New("validation-error: field NodeID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNodeAnnotations gets kubernetes cluster worker node annotations
|
// GetNodeAnnotations gets kubernetes cluster worker node annotations
|
||||||
func (k8s K8S) GetNodeAnnotations(ctx context.Context, req GetNodeAnnotationsRequest) (string, error) {
|
func (k8s K8S) GetNodeAnnotations(ctx context.Context, req GetNodeAnnotationsRequest) (string, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return "", validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/getNodeAnnotations"
|
url := "/cloudapi/k8s/getNodeAnnotations"
|
||||||
|
|||||||
@@ -2,37 +2,29 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get node labels
|
// Request struct for get node labels
|
||||||
type GetNodeLabelsRequest struct {
|
type GetNodeLabelsRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// Node ID
|
// Node ID
|
||||||
// Required: false
|
// Required: true
|
||||||
NodeID uint64 `url:"nodeId" json:"nodeId"`
|
NodeID uint64 `url:"nodeId" json:"nodeId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq GetNodeLabelsRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.NodeID == 0 {
|
|
||||||
return errors.New("validation-error: field NodeID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNodeLabels gets kubernetes cluster worker node labels
|
// GetNodeLabels gets kubernetes cluster worker node labels
|
||||||
func (k8s K8S) GetNodeLabels(ctx context.Context, req GetNodeLabelsRequest) (string, error) {
|
func (k8s K8S) GetNodeLabels(ctx context.Context, req GetNodeLabelsRequest) (string, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return "", validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/getNodeLabels"
|
url := "/cloudapi/k8s/getNodeLabels"
|
||||||
|
|||||||
@@ -2,37 +2,29 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get node taints
|
// Request struct for get node taints
|
||||||
type GetNodeTaintsRequest struct {
|
type GetNodeTaintsRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// Node ID
|
// Node ID
|
||||||
// Required: false
|
// Required: true
|
||||||
NodeID uint64 `url:"nodeId" json:"nodeId"`
|
NodeID uint64 `url:"nodeId" json:"nodeId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq GetNodeTaintsRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.NodeID == 0 {
|
|
||||||
return errors.New("validation-error: field NodeID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNodeTaints gets kubernetes cluster worker node taints
|
// GetNodeTaints gets kubernetes cluster worker node taints
|
||||||
func (k8s K8S) GetNodeTaints(ctx context.Context, req GetNodeTaintsRequest) (string, error) {
|
func (k8s K8S) GetNodeTaints(ctx context.Context, req GetNodeTaintsRequest) (string, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return "", validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/getNodeTaints"
|
url := "/cloudapi/k8s/getNodeTaints"
|
||||||
|
|||||||
@@ -101,6 +101,9 @@ type RecordK8S struct {
|
|||||||
// Name
|
// Name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Network plugin
|
||||||
|
NetworkPlugin string `json:"networkPlugin"`
|
||||||
|
|
||||||
// Resource group ID
|
// Resource group ID
|
||||||
RGID uint64 `json:"rgId"`
|
RGID uint64 `json:"rgId"`
|
||||||
|
|
||||||
@@ -246,6 +249,9 @@ type ItemK8SCluster struct {
|
|||||||
// Name
|
// Name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Network plugin
|
||||||
|
NetworkPlugin string `json:"networkPlugin"`
|
||||||
|
|
||||||
// Resource group ID
|
// Resource group ID
|
||||||
RGID uint64 `json:"rgId"`
|
RGID uint64 `json:"rgId"`
|
||||||
|
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for restore kubernetes cluster
|
// Request struct for restore kubernetes cluster
|
||||||
type RestoreRequest struct {
|
type RestoreRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq RestoreRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore restore kubernetes cluster from Recycle Bin
|
// Restore restore kubernetes cluster from Recycle Bin
|
||||||
func (k8s K8S) Restore(ctx context.Context, req RestoreRequest) (bool, error) {
|
func (k8s K8S) Restore(ctx context.Context, req RestoreRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/restore"
|
url := "/cloudapi/k8s/restore"
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for start kubernetes cluster
|
// Request struct for start kubernetes cluster
|
||||||
type StartRequest struct {
|
type StartRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq StartRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts kubernetes cluster by ID
|
// Start starts kubernetes cluster by ID
|
||||||
func (k8s K8S) Start(ctx context.Context, req StartRequest) (bool, error) {
|
func (k8s K8S) Start(ctx context.Context, req StartRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/start"
|
url := "/cloudapi/k8s/start"
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for stop kubernetes cluster
|
// Request struct for stop kubernetes cluster
|
||||||
type StopRequest struct {
|
type StopRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq StopRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops kubernetes cluster by ID
|
// Stop stops kubernetes cluster by ID
|
||||||
func (k8s K8S) Stop(ctx context.Context, req StopRequest) (bool, error) {
|
func (k8s K8S) Stop(ctx context.Context, req StopRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/stop"
|
url := "/cloudapi/k8s/stop"
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for update kubernetes cluster
|
// Request struct for update kubernetes cluster
|
||||||
type UpdateRequest struct {
|
type UpdateRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// New name to set.
|
// New name to set.
|
||||||
// If empty string is passed, name is not updated
|
// If empty string is passed, name is not updated
|
||||||
@@ -24,19 +25,13 @@ type UpdateRequest struct {
|
|||||||
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq UpdateRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update updates name or description of Kubernetes cluster
|
// Update updates name or description of Kubernetes cluster
|
||||||
func (k8s K8S) Update(ctx context.Context, req UpdateRequest) (bool, error) {
|
func (k8s K8S) Update(ctx context.Context, req UpdateRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/update"
|
url := "/cloudapi/k8s/update"
|
||||||
|
|||||||
@@ -2,57 +2,47 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for add worker to a kubernetes cluster
|
// Request struct for add worker to a kubernetes cluster
|
||||||
type WorkerAddRequest struct {
|
type WorkerAddRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// ID of the workers compute group
|
// ID of the workers compute group
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId"`
|
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"`
|
||||||
|
|
||||||
// How many worker nodes to add
|
// How many worker nodes to add
|
||||||
// Required: true
|
// Required: true
|
||||||
Num uint64 `url:"num" json:"num"`
|
Num uint64 `url:"num" json:"num" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq WorkerAddRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkersGroupID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Num == 0 {
|
|
||||||
return errors.New("validation-error: field Num can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorkerAdd add worker nodes to a Kubernetes cluster
|
// WorkerAdd add worker nodes to a Kubernetes cluster
|
||||||
func (k8s K8S) WorkerAdd(ctx context.Context, req WorkerAddRequest) (bool, error) {
|
func (k8s K8S) WorkerAdd(ctx context.Context, req WorkerAddRequest) ([]uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/workerAdd"
|
url := "/cloudapi/k8s/workerAdd"
|
||||||
|
|
||||||
res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
result := make([]uint64, 0)
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|||||||
@@ -2,45 +2,34 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for hard reset kubernetes cluster
|
// Request struct for hard reset kubernetes cluster
|
||||||
type WorkerResetRequest struct {
|
type WorkerResetRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// ID of the workers compute group
|
// ID of the workers compute group
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId"`
|
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"`
|
||||||
|
|
||||||
// Compute ID of worker node to reset
|
// Compute ID of worker node to reset
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkerID uint64 `url:"workerId" json:"workerId"`
|
WorkerID uint64 `url:"workerId" json:"workerId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq WorkerResetRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkersGroupID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkerID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkerID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorkerReset hard reset (compute start + stop) worker node of the Kubernetes cluster
|
// WorkerReset hard reset (compute start + stop) worker node of the Kubernetes cluster
|
||||||
func (k8s K8S) WorkerReset(ctx context.Context, req WorkerResetRequest) (bool, error) {
|
func (k8s K8S) WorkerReset(ctx context.Context, req WorkerResetRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/workerReset"
|
url := "/cloudapi/k8s/workerReset"
|
||||||
|
|||||||
@@ -2,45 +2,34 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for restart worker node
|
// Request struct for restart worker node
|
||||||
type WorkerRestartRequest struct {
|
type WorkerRestartRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// ID of the workers compute group
|
// ID of the workers compute group
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId"`
|
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"`
|
||||||
|
|
||||||
// Compute ID of worker node to restart
|
// Compute ID of worker node to restart
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkerID uint64 `url:"workerId" json:"workerId"`
|
WorkerID uint64 `url:"workerId" json:"workerId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq WorkerRestartRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkersGroupID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkerID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkerID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorkerRestart soft restart (reboot OS) worker node of the Kubernetes cluster
|
// WorkerRestart soft restart (reboot OS) worker node of the Kubernetes cluster
|
||||||
func (k8s K8S) WorkerRestart(ctx context.Context, req WorkerRestartRequest) (bool, error) {
|
func (k8s K8S) WorkerRestart(ctx context.Context, req WorkerRestartRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/workerRestart"
|
url := "/cloudapi/k8s/workerRestart"
|
||||||
|
|||||||
@@ -2,20 +2,21 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for add workers group
|
// Request struct for add workers group
|
||||||
type WorkersGroupAddRequest struct {
|
type WorkersGroupAddRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// Worker group name
|
// Worker group name
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// ID of SEP to create boot disks for default worker nodes group. Uses images SEP ID if not set
|
// ID of SEP to create boot disks for default worker nodes group. Uses images SEP ID if not set
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -57,33 +58,25 @@ type WorkersGroupAddRequest struct {
|
|||||||
WorkerDisk uint64 `url:"workerDisk,omitempty" json:"workerDisk,omitempty"`
|
WorkerDisk uint64 `url:"workerDisk,omitempty" json:"workerDisk,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq WorkersGroupAddRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name must be set")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WorkersGroupAdd adds workers group to Kubernetes cluster
|
// WorkersGroupAdd adds workers group to Kubernetes cluster
|
||||||
func (k8s K8S) WorkersGroupAdd(ctx context.Context, req WorkersGroupAddRequest) (bool, error) {
|
func (k8s K8S) WorkersGroupAdd(ctx context.Context, req WorkersGroupAddRequest) (uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return 0, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/workersGroupAdd"
|
url := "/cloudapi/k8s/workersGroupAdd"
|
||||||
|
|
||||||
res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseBool(string(res))
|
result, err := strconv.ParseUint(string(res), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|||||||
@@ -2,38 +2,30 @@ package k8s
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete workers group
|
// Request struct for delete workers group
|
||||||
type WorkersGroupDeleteRequest struct {
|
type WorkersGroupDeleteRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// Worker group ID
|
// Worker group ID
|
||||||
// Required: true
|
// Required: true
|
||||||
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId"`
|
WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq WorkersGroupDeleteRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.WorkersGroupID == 0 {
|
|
||||||
return errors.New("validation-error: field WorkersGroupID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorkersGroupDelete deletes workers group from Kubernetes cluster
|
// WorkersGroupDelete deletes workers group from Kubernetes cluster
|
||||||
func (k8s K8S) WorkersGroupDelete(ctx context.Context, req WorkersGroupDeleteRequest) (bool, error) {
|
func (k8s K8S) WorkersGroupDelete(ctx context.Context, req WorkersGroupDeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/workersGroupDelete"
|
url := "/cloudapi/k8s/workersGroupDelete"
|
||||||
|
|||||||
@@ -3,37 +3,29 @@ package k8s
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for get information about worker group
|
// Request struct for get information about worker group
|
||||||
type WorkersGroupGetByNameRequest struct {
|
type WorkersGroupGetByNameRequest struct {
|
||||||
// Kubernetes cluster ID
|
// Kubernetes cluster ID
|
||||||
// Required: true
|
// Required: true
|
||||||
K8SID uint64 `url:"k8sId" json:"k8sId"`
|
K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"`
|
||||||
|
|
||||||
// Worker group name
|
// Worker group name
|
||||||
// Required: true
|
// Required: true
|
||||||
GroupName string `url:"groupName" json:"groupName"`
|
GroupName string `url:"groupName" json:"groupName" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (krq WorkersGroupGetByNameRequest) validate() error {
|
|
||||||
if krq.K8SID == 0 {
|
|
||||||
return errors.New("validation-error: field K8SID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.GroupName == "" {
|
|
||||||
return errors.New("validation-error: field WorkersGroupID can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WorkersGroupGetByName gets worker group metadata by name
|
// WorkersGroupGetByName gets worker group metadata by name
|
||||||
func (k8s K8S) WorkersGroupGetByName(ctx context.Context, req WorkersGroupGetByNameRequest) (*RecordK8SGroups, error) {
|
func (k8s K8S) WorkersGroupGetByName(ctx context.Context, req WorkersGroupGetByNameRequest) (*RecordK8SGroups, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return nil, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/k8s/workersGroupGetByName"
|
url := "/cloudapi/k8s/workersGroupGetByName"
|
||||||
|
|||||||
@@ -2,34 +2,35 @@ package kvmppc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for create KVM PowerPC VM
|
// Request struct for create KVM PowerPC VM
|
||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
// ID of the resource group, which will own this VM
|
// ID of the resource group, which will own this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RGID uint64 `url:"rgId" json:"rgId"`
|
RGID uint64 `url:"rgId" json:"rgId" validate:"required"`
|
||||||
|
|
||||||
// Name of this VM.
|
// Name of this VM.
|
||||||
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Number CPUs to allocate to this VM
|
// Number CPUs to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
CPU uint64 `url:"cpu" json:"cpu"`
|
CPU uint64 `url:"cpu" json:"cpu" validate:"required"`
|
||||||
|
|
||||||
// Volume of RAM in MB to allocate to this VM
|
// Volume of RAM in MB to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RAM uint64 `url:"ram" json:"ram"`
|
RAM uint64 `url:"ram" json:"ram" validate:"required"`
|
||||||
|
|
||||||
// ID of the OS image to base this VM on;
|
// ID of the OS image to base this VM on;
|
||||||
// Could be boot disk image or CD-ROM image
|
// Could be boot disk image or CD-ROM image
|
||||||
// Required: true
|
// Required: true
|
||||||
ImageID uint64 `url:"imageId" json:"imageId"`
|
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
|
||||||
|
|
||||||
// Size of the boot disk in GB
|
// Size of the boot disk in GB
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -50,7 +51,7 @@ type CreateRequest struct {
|
|||||||
// - EXTNET
|
// - EXTNET
|
||||||
// - NONE
|
// - NONE
|
||||||
// Required: false
|
// Required: false
|
||||||
NetType string `url:"netType,omitempty" json:"netType,omitempty"`
|
NetType string `url:"netType,omitempty" json:"netType,omitempty" validate:"omitempty,kvmNetType"`
|
||||||
|
|
||||||
// Network ID for connect to,
|
// Network ID for connect to,
|
||||||
// for EXTNET - external network ID,
|
// for EXTNET - external network ID,
|
||||||
@@ -84,31 +85,13 @@ type CreateRequest struct {
|
|||||||
IPAType string `url:"ipaType,omitempty" json:"ipaType,omitempty"`
|
IPAType string `url:"ipaType,omitempty" json:"ipaType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq CreateRequest) validate() error {
|
|
||||||
if krq.RGID == 0 {
|
|
||||||
return errors.New("validation-error: field RGID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
if krq.CPU == 0 {
|
|
||||||
return errors.New("validation-error: field CPU can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.RAM == 0 {
|
|
||||||
return errors.New("validation-error: field RAM can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.ImageID == 0 {
|
|
||||||
return errors.New("validation-error: field ImageID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates KVM PowerPC VM based on specified OS image
|
// Create creates KVM PowerPC VM based on specified OS image
|
||||||
func (k KVMPPC) Create(ctx context.Context, req CreateRequest) (uint64, error) {
|
func (k KVMPPC) Create(ctx context.Context, req CreateRequest) (uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return 0, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/kvmppc/create"
|
url := "/cloudapi/kvmppc/create"
|
||||||
|
|||||||
@@ -2,42 +2,43 @@ package kvmppc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for create KVM PowerPC VM from scratch
|
// Request struct for create KVM PowerPC VM from scratch
|
||||||
type CreateBlankRequest struct {
|
type CreateBlankRequest struct {
|
||||||
// ID of the resource group, which will own this VM
|
// ID of the resource group, which will own this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RGID uint64 `url:"rgId" json:"rgId"`
|
RGID uint64 `url:"rgId" json:"rgId" validate:"required"`
|
||||||
|
|
||||||
// Name of this VM.
|
// Name of this VM.
|
||||||
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Number CPUs to allocate to this VM
|
// Number CPUs to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
CPU uint64 `url:"cpu" json:"cpu"`
|
CPU uint64 `url:"cpu" json:"cpu" validate:"required"`
|
||||||
|
|
||||||
// Volume of RAM in MB to allocate to this VM
|
// Volume of RAM in MB to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RAM uint64 `url:"ram" json:"ram"`
|
RAM uint64 `url:"ram" json:"ram" validate:"required"`
|
||||||
|
|
||||||
// Size of the boot disk in GB
|
// Size of the boot disk in GB
|
||||||
// Required: true
|
// Required: true
|
||||||
BootDisk uint64 `url:"bootDisk" json:"bootDisk"`
|
BootDisk uint64 `url:"bootDisk" json:"bootDisk" validate:"required"`
|
||||||
|
|
||||||
// ID of SEP to create boot disk on.
|
// ID of SEP to create boot disk on.
|
||||||
// Uses images SEP ID if not set
|
// Uses images SEP ID if not set
|
||||||
// Required: true
|
// Required: true
|
||||||
SEPID uint64 `url:"sepId" json:"sepId"`
|
SEPID uint64 `url:"sepId" json:"sepId" validate:"required"`
|
||||||
|
|
||||||
// Pool to use if SEP ID is set, can be also empty if needed to be chosen by system
|
// Pool to use if SEP ID is set, can be also empty if needed to be chosen by system
|
||||||
// Required: true
|
// Required: true
|
||||||
Pool string `url:"pool" json:"pool"`
|
Pool string `url:"pool" json:"pool" validate:"required"`
|
||||||
|
|
||||||
// Network type
|
// Network type
|
||||||
// Should be one of:
|
// Should be one of:
|
||||||
@@ -45,7 +46,7 @@ type CreateBlankRequest struct {
|
|||||||
// - EXTNET
|
// - EXTNET
|
||||||
// - NONE
|
// - NONE
|
||||||
// Required: false
|
// Required: false
|
||||||
NetType string `url:"netType,omitempty" json:"netType,omitempty"`
|
NetType string `url:"netType,omitempty" json:"netType,omitempty" validate:"omitempty,kvmNetType"`
|
||||||
|
|
||||||
// Network ID for connect to,
|
// Network ID for connect to,
|
||||||
// for EXTNET - external network ID,
|
// for EXTNET - external network ID,
|
||||||
@@ -63,37 +64,13 @@ type CreateBlankRequest struct {
|
|||||||
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq CreateBlankRequest) validate() error {
|
|
||||||
if krq.RGID == 0 {
|
|
||||||
return errors.New("validation-error: field RGID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
if krq.CPU == 0 {
|
|
||||||
return errors.New("validation-error: field CPU can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.RAM == 0 {
|
|
||||||
return errors.New("validation-error: field RAM can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.BootDisk == 0 {
|
|
||||||
return errors.New("validation-error: field BootDisk can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.SEPID == 0 {
|
|
||||||
return errors.New("validation-error: field SepID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Pool == "" {
|
|
||||||
return errors.New("validation-error: field Pool can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateBlank creates KVM PowerPC VM from scratch
|
// CreateBlank creates KVM PowerPC VM from scratch
|
||||||
func (k KVMPPC) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) {
|
func (k KVMPPC) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return 0, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/kvmppc/createBlank"
|
url := "/cloudapi/kvmppc/createBlank"
|
||||||
|
|||||||
@@ -2,34 +2,35 @@ package kvmx86
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for create KVM x86 VM
|
// Request struct for create KVM x86 VM
|
||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
// ID of the resource group, which will own this VM
|
// ID of the resource group, which will own this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RGID uint64 `url:"rgId" json:"rgId"`
|
RGID uint64 `url:"rgId" json:"rgId" validate:"required"`
|
||||||
|
|
||||||
// Name of this VM.
|
// Name of this VM.
|
||||||
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Number CPUs to allocate to this VM
|
// Number CPUs to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
CPU uint64 `url:"cpu" json:"cpu"`
|
CPU uint64 `url:"cpu" json:"cpu" validate:"required"`
|
||||||
|
|
||||||
// Volume of RAM in MB to allocate to this VM
|
// Volume of RAM in MB to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RAM uint64 `url:"ram" json:"ram"`
|
RAM uint64 `url:"ram" json:"ram" validate:"required"`
|
||||||
|
|
||||||
// ID of the OS image to base this VM on;
|
// ID of the OS image to base this VM on;
|
||||||
// Could be boot disk image or CD-ROM image
|
// Could be boot disk image or CD-ROM image
|
||||||
// Required: true
|
// Required: true
|
||||||
ImageID uint64 `url:"imageId" json:"imageId"`
|
ImageID uint64 `url:"imageId" json:"imageId" validate:"required"`
|
||||||
|
|
||||||
// Size of the boot disk in GB
|
// Size of the boot disk in GB
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -50,7 +51,7 @@ type CreateRequest struct {
|
|||||||
// - EXTNET
|
// - EXTNET
|
||||||
// - NONE
|
// - NONE
|
||||||
// Required: false
|
// Required: false
|
||||||
NetType string `url:"netType,omitempty" json:"netType,omitempty"`
|
NetType string `url:"netType,omitempty" json:"netType,omitempty" validate:"omitempty,kvmNetType"`
|
||||||
|
|
||||||
// Network ID for connect to,
|
// Network ID for connect to,
|
||||||
// for EXTNET - external network ID,
|
// for EXTNET - external network ID,
|
||||||
@@ -84,31 +85,13 @@ type CreateRequest struct {
|
|||||||
IPAType string `url:"ipaType,omitempty" json:"ipaType,omitempty"`
|
IPAType string `url:"ipaType,omitempty" json:"ipaType,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq CreateRequest) validate() error {
|
|
||||||
if krq.RGID == 0 {
|
|
||||||
return errors.New("validation-error: field RGID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
if krq.CPU == 0 {
|
|
||||||
return errors.New("validation-error: field CPU can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.RAM == 0 {
|
|
||||||
return errors.New("validation-error: field RAM can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.ImageID == 0 {
|
|
||||||
return errors.New("validation-error: field ImageID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates KVM x86 VM based on specified OS image
|
// Create creates KVM x86 VM based on specified OS image
|
||||||
func (k KVMX86) Create(ctx context.Context, req CreateRequest) (uint64, error) {
|
func (k KVMX86) Create(ctx context.Context, req CreateRequest) (uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return 0, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/kvmx86/create"
|
url := "/cloudapi/kvmx86/create"
|
||||||
|
|||||||
@@ -2,42 +2,43 @@ package kvmx86
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for create KVM x86 VM from scratch
|
// Request struct for create KVM x86 VM from scratch
|
||||||
type CreateBlankRequest struct {
|
type CreateBlankRequest struct {
|
||||||
// ID of the resource group, which will own this VM
|
// ID of the resource group, which will own this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RGID uint64 `url:"rgId" json:"rgId"`
|
RGID uint64 `url:"rgId" json:"rgId" validate:"required"`
|
||||||
|
|
||||||
// Name of this VM.
|
// Name of this VM.
|
||||||
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
// Must be unique among all VMs (including those in DELETED state) in target resource group
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
// Number CPUs to allocate to this VM
|
// Number CPUs to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
CPU uint64 `url:"cpu" json:"cpu"`
|
CPU uint64 `url:"cpu" json:"cpu" validate:"required"`
|
||||||
|
|
||||||
// Volume of RAM in MB to allocate to this VM
|
// Volume of RAM in MB to allocate to this VM
|
||||||
// Required: true
|
// Required: true
|
||||||
RAM uint64 `url:"ram" json:"ram"`
|
RAM uint64 `url:"ram" json:"ram" validate:"required"`
|
||||||
|
|
||||||
// Size of the boot disk in GB
|
// Size of the boot disk in GB
|
||||||
// Required: true
|
// Required: true
|
||||||
BootDisk uint64 `url:"bootDisk" json:"bootDisk"`
|
BootDisk uint64 `url:"bootDisk" json:"bootDisk" validate:"required"`
|
||||||
|
|
||||||
// ID of SEP to create boot disk on.
|
// ID of SEP to create boot disk on.
|
||||||
// Uses images SEP ID if not set
|
// Uses images SEP ID if not set
|
||||||
// Required: true
|
// Required: true
|
||||||
SEPID uint64 `url:"sepId" json:"sepId"`
|
SEPID uint64 `url:"sepId" json:"sepId" validate:"required"`
|
||||||
|
|
||||||
// Pool to use if sepId is set, can be also empty if needed to be chosen by system
|
// Pool to use if sepId is set, can be also empty if needed to be chosen by system
|
||||||
// Required: true
|
// Required: true
|
||||||
Pool string `url:"pool" json:"pool"`
|
Pool string `url:"pool" json:"pool" validate:"required"`
|
||||||
|
|
||||||
// Network type
|
// Network type
|
||||||
// Should be one of:
|
// Should be one of:
|
||||||
@@ -45,7 +46,7 @@ type CreateBlankRequest struct {
|
|||||||
// - EXTNET
|
// - EXTNET
|
||||||
// - NONE
|
// - NONE
|
||||||
// Required: false
|
// Required: false
|
||||||
NetType string `url:"netType,omitempty" json:"netType,omitempty"`
|
NetType string `url:"netType,omitempty" json:"netType,omitempty" validate:"omitempty,kvmNetType"`
|
||||||
|
|
||||||
// Network ID for connect to,
|
// Network ID for connect to,
|
||||||
// for EXTNET - external network ID,
|
// for EXTNET - external network ID,
|
||||||
@@ -63,37 +64,13 @@ type CreateBlankRequest struct {
|
|||||||
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
Description string `url:"desc,omitempty" json:"desc,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (krq CreateBlankRequest) validate() error {
|
|
||||||
if krq.RGID == 0 {
|
|
||||||
return errors.New("validation-error: field RGID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Name == "" {
|
|
||||||
return errors.New("validation-error: field Name can not be empty")
|
|
||||||
}
|
|
||||||
if krq.CPU == 0 {
|
|
||||||
return errors.New("validation-error: field CPU can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.RAM == 0 {
|
|
||||||
return errors.New("validation-error: field RAM can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.BootDisk == 0 {
|
|
||||||
return errors.New("validation-error: field BootDisk can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.SEPID == 0 {
|
|
||||||
return errors.New("validation-error: field SepID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if krq.Pool == "" {
|
|
||||||
return errors.New("validation-error: field Pool can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateBlank creates KVM x86 VM from scratch
|
// CreateBlank creates KVM x86 VM from scratch
|
||||||
func (k KVMX86) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) {
|
func (k KVMX86) CreateBlank(ctx context.Context, req CreateBlankRequest) (uint64, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return 0, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/kvmx86/createBlank"
|
url := "/cloudapi/kvmx86/createBlank"
|
||||||
|
|||||||
@@ -2,20 +2,21 @@ package lb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for create backend
|
// Request struct for create backend
|
||||||
type BackendCreateRequest struct {
|
type BackendCreateRequest struct {
|
||||||
// ID of the load balancer instance to backendCreate
|
// ID of the load balancer instance to backendCreate
|
||||||
// Required: true
|
// Required: true
|
||||||
LBID uint64 `url:"lbId" json:"lbId"`
|
LBID uint64 `url:"lbId" json:"lbId" validate:"required"`
|
||||||
|
|
||||||
// Must be unique among all backends of this load balancer - name of the new backend to create
|
// Must be unique among all backends of this load balancer - name of the new backend to create
|
||||||
// Required: true
|
// Required: true
|
||||||
BackendName string `url:"backendName" json:"backendName"`
|
BackendName string `url:"backendName" json:"backendName" validate:"required"`
|
||||||
|
|
||||||
// Algorithm
|
// Algorithm
|
||||||
// Should be one of:
|
// Should be one of:
|
||||||
@@ -23,7 +24,7 @@ type BackendCreateRequest struct {
|
|||||||
// - static-rr
|
// - static-rr
|
||||||
// - leastconn
|
// - leastconn
|
||||||
// Required: false
|
// Required: false
|
||||||
Algorithm string `url:"algorithm,omitempty" json:"algorithm,omitempty"`
|
Algorithm string `url:"algorithm,omitempty" json:"algorithm,omitempty" validate:"omitempty,lbAlgorithm"`
|
||||||
|
|
||||||
// Interval in milliseconds between two consecutive availability
|
// Interval in milliseconds between two consecutive availability
|
||||||
// checks of the server that is considered available
|
// checks of the server that is considered available
|
||||||
@@ -66,22 +67,13 @@ type BackendCreateRequest struct {
|
|||||||
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lbrq BackendCreateRequest) validate() error {
|
|
||||||
if lbrq.LBID == 0 {
|
|
||||||
return errors.New("validation-error: field LBID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if lbrq.BackendName == "" {
|
|
||||||
return errors.New("validation-error: field BackendName can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackendCreate creates new backend on the specified load balancer
|
// BackendCreate creates new backend on the specified load balancer
|
||||||
func (l LB) BackendCreate(ctx context.Context, req BackendCreateRequest) (bool, error) {
|
func (l LB) BackendCreate(ctx context.Context, req BackendCreateRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/lb/backendCreate"
|
url := "/cloudapi/lb/backendCreate"
|
||||||
|
|||||||
@@ -2,39 +2,31 @@ package lb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete backend
|
// Request struct for delete backend
|
||||||
type BackendDeleteRequest struct {
|
type BackendDeleteRequest struct {
|
||||||
// ID of the load balancer instance to BackendDelete
|
// ID of the load balancer instance to BackendDelete
|
||||||
// Required: true
|
// Required: true
|
||||||
LBID uint64 `url:"lbId" json:"lbId"`
|
LBID uint64 `url:"lbId" json:"lbId" validate:"required"`
|
||||||
|
|
||||||
// Cannot be emtpy string - name of the backend to delete
|
// Cannot be emtpy string - name of the backend to delete
|
||||||
// Required: true
|
// Required: true
|
||||||
BackendName string `url:"backendName" json:"backendName"`
|
BackendName string `url:"backendName" json:"backendName" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (lbrq BackendDeleteRequest) validate() error {
|
|
||||||
if lbrq.LBID == 0 {
|
|
||||||
return errors.New("validation-error: field LBID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if lbrq.BackendName == "" {
|
|
||||||
return errors.New("validation-error: field BackendName can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackendDelete deletes backend from the specified load balancer.
|
// BackendDelete deletes backend from the specified load balancer.
|
||||||
// Warning: you cannot undo this action!
|
// Warning: you cannot undo this action!
|
||||||
func (l LB) BackendDelete(ctx context.Context, req BackendDeleteRequest) (bool, error) {
|
func (l LB) BackendDelete(ctx context.Context, req BackendDeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/lb/backendDelete"
|
url := "/cloudapi/lb/backendDelete"
|
||||||
|
|||||||
@@ -2,32 +2,33 @@ package lb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for add server definition to the backend
|
// Request struct for add server definition to the backend
|
||||||
type BackendServerAddRequest struct {
|
type BackendServerAddRequest struct {
|
||||||
// ID of the load balancer instance to BackendServerAdd
|
// ID of the load balancer instance to BackendServerAdd
|
||||||
// Required: true
|
// Required: true
|
||||||
LBID uint64 `url:"lbId" json:"lbId"`
|
LBID uint64 `url:"lbId" json:"lbId" validate:"required"`
|
||||||
|
|
||||||
// Must match one of the existing backens - name of the backend to add servers to
|
// Must match one of the existing backens - name of the backend to add servers to
|
||||||
// Required: true
|
// Required: true
|
||||||
BackendName string `url:"backendName" json:"backendName"`
|
BackendName string `url:"backendName" json:"backendName" validate:"required"`
|
||||||
|
|
||||||
// Must be unique among all servers defined for this backend - name of the server definition to add
|
// Must be unique among all servers defined for this backend - name of the server definition to add
|
||||||
// Required: true
|
// Required: true
|
||||||
ServerName string `url:"serverName" json:"serverName"`
|
ServerName string `url:"serverName" json:"serverName" validate:"required"`
|
||||||
|
|
||||||
// IP address of the server
|
// IP address of the server
|
||||||
// Required: true
|
// Required: true
|
||||||
Address string `url:"address" json:"address"`
|
Address string `url:"address" json:"address" validate:"required"`
|
||||||
|
|
||||||
// Port number on the server
|
// Port number on the server
|
||||||
// Required: true
|
// Required: true
|
||||||
Port uint64 `url:"port" json:"port"`
|
Port uint64 `url:"port" json:"port" validate:"required"`
|
||||||
|
|
||||||
// Set to disabled if this server should be used regardless of its state
|
// Set to disabled if this server should be used regardless of its state
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -71,31 +72,13 @@ type BackendServerAddRequest struct {
|
|||||||
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lbrq BackendServerAddRequest) validate() error {
|
|
||||||
if lbrq.LBID == 0 {
|
|
||||||
return errors.New("validation-error: field LBID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if lbrq.BackendName == "" {
|
|
||||||
return errors.New("validation-error: field BackendName can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.ServerName == "" {
|
|
||||||
return errors.New("validation-error: field ServerName can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.Address == "" {
|
|
||||||
return errors.New("validation-error: field Address can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.Port == 0 {
|
|
||||||
return errors.New("validation-error: field Port can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackendServerAdd adds server definition to the backend on the specified load balancer
|
// BackendServerAdd adds server definition to the backend on the specified load balancer
|
||||||
func (l LB) BackendServerAdd(ctx context.Context, req BackendServerAddRequest) (bool, error) {
|
func (l LB) BackendServerAdd(ctx context.Context, req BackendServerAddRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/lb/backendServerAdd"
|
url := "/cloudapi/lb/backendServerAdd"
|
||||||
|
|||||||
@@ -2,46 +2,35 @@ package lb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for delete server definition
|
// Request struct for delete server definition
|
||||||
type BackendServerDeleteRequest struct {
|
type BackendServerDeleteRequest struct {
|
||||||
// ID of the load balancer instance to BackendServerDelete
|
// ID of the load balancer instance to BackendServerDelete
|
||||||
// Required: true
|
// Required: true
|
||||||
LBID uint64 `url:"lbId" json:"lbId"`
|
LBID uint64 `url:"lbId" json:"lbId" validate:"required"`
|
||||||
|
|
||||||
// Must match one of the existing backens - name of the backend to add servers to
|
// Must match one of the existing backens - name of the backend to add servers to
|
||||||
// Required: true
|
// Required: true
|
||||||
BackendName string `url:"backendName" json:"backendName"`
|
BackendName string `url:"backendName" json:"backendName" validate:"required"`
|
||||||
|
|
||||||
// Must be unique among all servers defined for this backend - name of the server definition to add
|
// Must be unique among all servers defined for this backend - name of the server definition to add
|
||||||
// Required: true
|
// Required: true
|
||||||
ServerName string `url:"serverName" json:"serverName"`
|
ServerName string `url:"serverName" json:"serverName" validate:"required"`
|
||||||
}
|
|
||||||
|
|
||||||
func (lbrq BackendServerDeleteRequest) validate() error {
|
|
||||||
if lbrq.LBID == 0 {
|
|
||||||
return errors.New("validation-error: field LBID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if lbrq.BackendName == "" {
|
|
||||||
return errors.New("validation-error: field BackendName can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.ServerName == "" {
|
|
||||||
return errors.New("validation-error: field ServerName can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackendServerDelete deletes server definition from the backend on the specified load balancer.
|
// BackendServerDelete deletes server definition from the backend on the specified load balancer.
|
||||||
// Warning: you cannot undo this action!
|
// Warning: you cannot undo this action!
|
||||||
func (l LB) BackendServerDelete(ctx context.Context, req BackendServerDeleteRequest) (bool, error) {
|
func (l LB) BackendServerDelete(ctx context.Context, req BackendServerDeleteRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/lb/backendServerDelete"
|
url := "/cloudapi/lb/backendServerDelete"
|
||||||
|
|||||||
@@ -2,32 +2,33 @@ package lb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for update server
|
// Request struct for update server
|
||||||
type BackendServerUpdateRequest struct {
|
type BackendServerUpdateRequest struct {
|
||||||
// ID of the load balancer instance to BackendServerAdd
|
// ID of the load balancer instance to BackendServerAdd
|
||||||
// Required: true
|
// Required: true
|
||||||
LBID uint64 `url:"lbId" json:"lbId"`
|
LBID uint64 `url:"lbId" json:"lbId" validate:"required"`
|
||||||
|
|
||||||
// Must match one of the existing backens - name of the backend to add servers to
|
// Must match one of the existing backens - name of the backend to add servers to
|
||||||
// Required: true
|
// Required: true
|
||||||
BackendName string `url:"backendName" json:"backendName"`
|
BackendName string `url:"backendName" json:"backendName" validate:"required"`
|
||||||
|
|
||||||
// Must be unique among all servers defined for this backend - name of the server definition to add
|
// Must be unique among all servers defined for this backend - name of the server definition to add
|
||||||
// Required: true
|
// Required: true
|
||||||
ServerName string `url:"serverName" json:"serverName"`
|
ServerName string `url:"serverName" json:"serverName" validate:"required"`
|
||||||
|
|
||||||
// IP address of the server
|
// IP address of the server
|
||||||
// Required: true
|
// Required: true
|
||||||
Address string `url:"address" json:"address"`
|
Address string `url:"address" json:"address" validate:"required"`
|
||||||
|
|
||||||
// Port number on the server
|
// Port number on the server
|
||||||
// Required: true
|
// Required: true
|
||||||
Port uint64 `url:"port" json:"port"`
|
Port uint64 `url:"port" json:"port" validate:"required"`
|
||||||
|
|
||||||
// Set to disabled if this server should be used regardless of its state
|
// Set to disabled if this server should be used regardless of its state
|
||||||
// Required: false
|
// Required: false
|
||||||
@@ -71,31 +72,13 @@ type BackendServerUpdateRequest struct {
|
|||||||
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lbrq BackendServerUpdateRequest) validate() error {
|
|
||||||
if lbrq.LBID == 0 {
|
|
||||||
return errors.New("validation-error: field LBID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if lbrq.BackendName == "" {
|
|
||||||
return errors.New("validation-error: field BackendName can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.ServerName == "" {
|
|
||||||
return errors.New("validation-error: field ServerName can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.Address == "" {
|
|
||||||
return errors.New("validation-error: field Address can not be empty")
|
|
||||||
}
|
|
||||||
if lbrq.Port == 0 {
|
|
||||||
return errors.New("validation-error: field Port can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackendServerUpdate updates server definition on the backend of load balancer
|
// BackendServerUpdate updates server definition on the backend of load balancer
|
||||||
func (l LB) BackendServerUpdate(ctx context.Context, req BackendServerUpdateRequest) (bool, error) {
|
func (l LB) BackendServerUpdate(ctx context.Context, req BackendServerUpdateRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/lb/backendServerUpdate"
|
url := "/cloudapi/lb/backendServerUpdate"
|
||||||
|
|||||||
@@ -2,20 +2,21 @@ package lb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request struct for update backend
|
// Request struct for update backend
|
||||||
type BackendUpdateRequest struct {
|
type BackendUpdateRequest struct {
|
||||||
// ID of the load balancer instance to backendCreate
|
// ID of the load balancer instance to backendCreate
|
||||||
// Required: true
|
// Required: true
|
||||||
LBID uint64 `url:"lbId" json:"lbId"`
|
LBID uint64 `url:"lbId" json:"lbId" validate:"required"`
|
||||||
|
|
||||||
// Must be unique among all backends of this load balancer - name of the new backend to create
|
// Must be unique among all backends of this load balancer - name of the new backend to create
|
||||||
// Required: true
|
// Required: true
|
||||||
BackendName string `url:"backendName" json:"backendName"`
|
BackendName string `url:"backendName" json:"backendName" validate:"required"`
|
||||||
|
|
||||||
// Algorithm
|
// Algorithm
|
||||||
// Should be one of:
|
// Should be one of:
|
||||||
@@ -23,7 +24,7 @@ type BackendUpdateRequest struct {
|
|||||||
// - static-rr
|
// - static-rr
|
||||||
// - leastconn
|
// - leastconn
|
||||||
// Required: false
|
// Required: false
|
||||||
Algorithm string `url:"algorithm,omitempty" json:"algorithm,omitempty"`
|
Algorithm string `url:"algorithm,omitempty" json:"algorithm,omitempty" validate:"omitempty,lbAlgorithm"`
|
||||||
|
|
||||||
// Interval in milliseconds between two consecutive availability
|
// Interval in milliseconds between two consecutive availability
|
||||||
// checks of the server that is considered available
|
// checks of the server that is considered available
|
||||||
@@ -66,22 +67,13 @@ type BackendUpdateRequest struct {
|
|||||||
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
Weight uint64 `url:"weight,omitempty" json:"weight,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lbrq BackendUpdateRequest) validate() error {
|
|
||||||
if lbrq.LBID == 0 {
|
|
||||||
return errors.New("validation-error: field LBID can not be empty or equal to 0")
|
|
||||||
}
|
|
||||||
if lbrq.BackendName == "" {
|
|
||||||
return errors.New("validation-error: field BackendName can not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BackendUpdate updates existing backend on the specified load balancer. Note that backend name cannot be changed
|
// BackendUpdate updates existing backend on the specified load balancer. Note that backend name cannot be changed
|
||||||
func (l LB) BackendUpdate(ctx context.Context, req BackendUpdateRequest) (bool, error) {
|
func (l LB) BackendUpdate(ctx context.Context, req BackendUpdateRequest) (bool, error) {
|
||||||
err := req.validate()
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
for _, validationError := range validators.GetErrors(err) {
|
||||||
|
return false, validators.ValidationError(validationError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/lb/backendUpdate"
|
url := "/cloudapi/lb/backendUpdate"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user