Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a267d35ddf | |||
|
|
0bf073da93 | ||
|
|
562b6019d0 | ||
| bf5c01b40b | |||
|
|
095a18f27a | ||
|
|
84a090f9e8 |
55
CHANGELOG.md
55
CHANGELOG.md
@@ -1,58 +1,21 @@
|
|||||||
## Version 1.12.4
|
## Version 1.12.10
|
||||||
|
|
||||||
Методы `Audits` в cloudapi/compute, cloudbroker/compute, cloudapi/account, cloudbroker/account, cloudapi/vins, cloudbroker/vins, cloudapi/rg и cloudbroker/rg стали deprecated и в следующих версиях будут удалены, вместо них необходимо использовать метод `List` в cloudapi/audit и cloudbroker/audit с соответствующими фильтрами
|
Методы `Audits` в cloudapi/compute, cloudbroker/compute, cloudapi/account, cloudbroker/account, cloudapi/vins, cloudbroker/vins, cloudapi/rg и cloudbroker/rg стали deprecated и в следующих версиях будут удалены, вместо них необходимо использовать метод `List` в cloudapi/audit и cloudbroker/audit с соответствующими фильтрами
|
||||||
|
Метод `ListStacks` в cloudbroker/image стал deprecated и в следующих версиях будет удалён
|
||||||
|
Методы `AccessGrant`, `AccessGrantToPool`, `AccessRevoke`, `AccessRevokeToPool` в cloudbroker/sep стали deprecated и в следующих версиях будут удалены
|
||||||
|
|
||||||
|
Все методы группы `.SDN()` находятся в альфа-версии.
|
||||||
|
|
||||||
### Добавлено
|
### Добавлено
|
||||||
|
|
||||||
#### audit
|
#### ClientInterface
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | ---|
|
| --- | ---|
|
||||||
| BGOS-621 | Метод `List` в структура запроса `ListRequest` в cloudapi/audit |
|
| BGOS-673 | Добавлен mock для интерфейса ClientInterface с примерами |
|
||||||
| BGOS-621 | Опциональные поля `RGID`, `ComputeID`, `AccountID`, `VINSID`, `ServiceID`, `K8SID`, `FLIPGroupID`, `LBID`, `SEPID`, `NodeID`, `ExcludeAuditLines` в структуру запроса `ListRequest` в cloudbroker/audit |
|
|
||||||
|
|
||||||
#### compute
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-613 | Поля `UpdatedTime`, `DeletedBy`, `DeviceName`, `CreatedBy` в структуру ответа `ItemComputeDisk` в cloudapi/compute и в структуру ответа `ItemDisk` в cloudbroker/compute |
|
|
||||||
| BGOS-613 | Поле `LoaderMetaIso` в структуру ответа `RecordCompute` и структура `LoaderMetaIso` в cloudapi/compute и в cloudbroker/compute |
|
|
||||||
| BGOS-616 | Опциональные поля `PCISlot` и `BusNumber` в структуры запросов `DiskAdd` и `DiskAttach` в cloudapi/compute и cloudbroker/compute |
|
|
||||||
| BGOS-619 | Методы `StartMigrationOut` и `StopMigrationOut` и структуры запросов `StartMigrationOutRequest` и `StopMigrationOutRequest` в cloudbroker/compute |
|
|
||||||
| BGOS-619 | Структура `OSUser` в структуру запроса `StopMigrationINRequest` в cloudbroker/compute |
|
|
||||||
|
|
||||||
#### image
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-614 | Поле `StoragePolicyID` в структуру ответа `ItemImage` в cloudapi/image |
|
|
||||||
| BGOS-617 | Опциональное поле `StoragePolicyID` в структуры запроса `ListRequest` в cloudapi/image и cloudbroker/image |
|
|
||||||
|
|
||||||
#### vins
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-615 | Поле `ZoneID` в структуры ответа `RecordDHCP`, `RecordGW`, `RecordNAT`, `RecordVNFDev` в cloudapi/vins и `InfoVNF` и `VNFDev` в cloudbroker/vins |
|
|
||||||
| BGOS-615 | Поля `SecGroups`, `EnableSecGroups` в структуру ответа `ItemVNFInterface` в cloudapi/vins и `ItemInterface` в cloudbroker/vins |
|
|
||||||
|
|
||||||
### Исправлено
|
|
||||||
|
|
||||||
#### compute
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-619 | Ошибка работы фильтра `SortBy` в методе `MigrateStorageList` в cloudbroker/compute |
|
|
||||||
|
|
||||||
#### storage policy
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-620 | Поле `AccountID` в структуре запроса `ListRequest` стало опциональным в cloudapi/stpolicy |
|
|
||||||
|
|
||||||
### Удалено
|
### Удалено
|
||||||
|
|
||||||
#### audit
|
#### logical ports
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-621 | Поле `Tags` в структуре ответа `ItemAudit` в cloudbroker/audit |
|
| BGOS-668 | Поля `LogicalPortID` и `VersionID` в структуре запроса `CreateRequest` |
|
||||||
|
|
||||||
#### disks
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-618 | Поле `IOPS` из структуры запроса `CreateRequest` в cloudapi/disks и в cloudbroker/disks |
|
|
||||||
|
|
||||||
|
|
||||||
67
README.md
67
README.md
@@ -27,6 +27,7 @@ Decort SDK - это библиотека, написанная на языке G
|
|||||||
- [Список API](#список-api)
|
- [Список API](#список-api)
|
||||||
- [Cloudapi](#cloudapi)
|
- [Cloudapi](#cloudapi)
|
||||||
- [Cloudbroker](#cloudbroker)
|
- [Cloudbroker](#cloudbroker)
|
||||||
|
- [SDN](#sdn)
|
||||||
- [Работа с библиотекой](#работа-с-библиотекой)
|
- [Работа с библиотекой](#работа-с-библиотекой)
|
||||||
- [Настройка конфигурации клиента](#настройка-конфигурации-клиента)
|
- [Настройка конфигурации клиента](#настройка-конфигурации-клиента)
|
||||||
- [Пример конфигурации клиента](#пример-конфигурации-клиента)
|
- [Пример конфигурации клиента](#пример-конфигурации-клиента)
|
||||||
@@ -82,6 +83,8 @@ Decort SDK - это библиотека, написанная на языке G
|
|||||||
- [Пример выполнения запроса](#пример-выполнения-запроса-4)
|
- [Пример выполнения запроса](#пример-выполнения-запроса-4)
|
||||||
- [Проверка соответствия версии платформы и версии dynamix](#проверка-соответствия-версии-платформы-и-версии-dynamix)
|
- [Проверка соответствия версии платформы и версии dynamix](#проверка-соответствия-версии-платформы-и-версии-dynamix)
|
||||||
- [Пример выполнения запроса](#пример-выполнения-запроса-5)
|
- [Пример выполнения запроса](#пример-выполнения-запроса-5)
|
||||||
|
- [Создание mock клиента](#создание-mock-клиента)
|
||||||
|
- [Пример создания mock клиента](#пример-создания-mock-клиента)
|
||||||
|
|
||||||
## Установка
|
## Установка
|
||||||
|
|
||||||
@@ -174,7 +177,16 @@ go get -u repository.basistech.ru/BASIS/decort-golang-sdk
|
|||||||
`SDN` позволяет выполнять запросы к группе пользовательских конечных точек
|
`SDN` позволяет выполнять запросы к группе пользовательских конечных точек
|
||||||
Данная группа ручек позволяет выполнять следующие операции в платформе:
|
Данная группа ручек позволяет выполнять следующие операции в платформе:
|
||||||
|
|
||||||
- `AccessGroup` - управление группами доступа
|
- `Access group` - управление группами доступа;
|
||||||
|
- `Address pool` - управление пулами адресов;
|
||||||
|
- `DefaultSecurityPolicies` - управление политиками хранения по умолчанию;
|
||||||
|
- `ExtNet` - управление виртуальными сетями, отвечающими за внешний доступ;
|
||||||
|
- `FloatingIPs` - управление плавающими IP-адресами;
|
||||||
|
- `Logical ports` - управление логическими портами;
|
||||||
|
- `NetworkObjectGroups` - управление группами объектов сети;
|
||||||
|
- `Routers` - управление роутерами;
|
||||||
|
- `SecurityPolicies` - управление политиками хранения;
|
||||||
|
- `Segments` - управление сегментами;
|
||||||
|
|
||||||
## Работа с библиотекой
|
## Работа с библиотекой
|
||||||
|
|
||||||
@@ -367,7 +379,16 @@ func main() {
|
|||||||
- `pkg/cloudbroker/vins` - для `VINS`
|
- `pkg/cloudbroker/vins` - для `VINS`
|
||||||
- `pkg/cloudbroker/zone` - для `Zone`
|
- `pkg/cloudbroker/zone` - для `Zone`
|
||||||
- **sdn**:
|
- **sdn**:
|
||||||
- `pkg/sdn/access_groups` - для `AccessGroups`
|
- `pkg/sdn/acsgroups` - для `Access groups`
|
||||||
|
- `pkg/sdn/adrspools` - для `Address pool`
|
||||||
|
- `pkg/sdn/defsecpolicies` - для `DefaultSecurityPolicies`
|
||||||
|
- `pkg/sdn/external_networks` - для `ExtNet`
|
||||||
|
- `pkg/sdn/flips` - для `FloatingIPs`
|
||||||
|
- `pkg/sdn/logicalports` - для `Logical ports`
|
||||||
|
- `pkg/sdn/netobjgroups` - для `NetworkObjectGroups`
|
||||||
|
- `pkg/sdn/routers` - для `Routers`
|
||||||
|
- `pkg/sdn/secpolicies` - для `SecurityPolicies`
|
||||||
|
- `pkg/sdn/segments` - для `Segments`
|
||||||
|
|
||||||
Все поля структуры имеют описание, в которых содержится:
|
Все поля структуры имеют описание, в которых содержится:
|
||||||
|
|
||||||
@@ -570,7 +591,16 @@ func main() {
|
|||||||
|
|
||||||
Доступные методы для `.SDN()`:
|
Доступные методы для `.SDN()`:
|
||||||
|
|
||||||
- `.AccessGroup()` - для работы с `AccessGroup`
|
- `.AccessGroup()` - для работы с `Access group`
|
||||||
|
- `.AddressPool()` - для работы с `Addres pool`
|
||||||
|
- `.DefaultSecurityPolicies()` - для работы с `DefaultSecurityPolicies`
|
||||||
|
- `.ExtNet()` - для работы с `ExtNet`
|
||||||
|
- `.FloatingIPs()` - для работы с `FloatingIPs`
|
||||||
|
- `.LogicalPorts()` - для работы с `Logical ports`
|
||||||
|
- `.NetworkObjectGroups()` - для работы с `NetworkObjectGroups`
|
||||||
|
- `.Routers()` - для работы с `Routers`
|
||||||
|
- `.SecurityPolicies()` - для работы с `SecurityPolicies`
|
||||||
|
- `.Segments()` - для работы с `Segments`
|
||||||
|
|
||||||
3. Вызвать метод, отвечающий за выполнение запроса и передать в него:
|
3. Вызвать метод, отвечающий за выполнение запроса и передать в него:
|
||||||
|
|
||||||
@@ -1682,3 +1712,34 @@ func main(){
|
|||||||
checkInfo, err := client.Check()
|
checkInfo, err := client.Check()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Создание mock клиента
|
||||||
|
|
||||||
|
Создание клиента происходит с помощью функции-строителя `NewMockDecortClient` из основного пакета `decort-sdk`. Функция принимает mock реализацию интерфейса interfaces.Calller, возвращает структуру `MockDecortClient`, с помощью которой можно производить unit тестирование API Decort SDK без подключения к серверу
|
||||||
|
|
||||||
|
#### Пример создания mock клиента
|
||||||
|
```go
|
||||||
|
package unit_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"go.uber.org/mock/gomock"
|
||||||
|
decortsdk "repository.basistech.ru/BASIS/decort-golang-sdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Пример юнит тестирования на моках
|
||||||
|
func TestClient(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
// Создаем mock интерфейса Caller
|
||||||
|
mockCaller := decortsdk.NewMockCaller(ctrl)
|
||||||
|
// Создаем mock интерфейса DecortClient
|
||||||
|
mockClient := decortsdk.NewMockDecortClient(mockCaller)
|
||||||
|
// ....
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Пример юнит теста можно посмотреть в файле [samples/client/client_test.go](samples/client/client_test.go)
|
||||||
|
|
||||||
|
При редактировании интерфеса interface.Caller необходимо перегенерировать Mock :
|
||||||
|
``` shell
|
||||||
|
make gen-mock
|
||||||
|
```
|
||||||
24
check.go
24
check.go
@@ -28,7 +28,13 @@ func (de DecortClient) Check() (*CheckInfo, error) {
|
|||||||
|
|
||||||
err = json.Unmarshal([]byte(strings.Replace(strings.Trim(string(res), `"`), "\\", "", -1)), &info)
|
err = json.Unmarshal([]byte(strings.Replace(strings.Trim(string(res), `"`), "\\", "", -1)), &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
var v string
|
||||||
|
json.Unmarshal([]byte(res), &v)
|
||||||
|
if _, exists := constants.VersionMap[v]; exists {
|
||||||
|
info.Version = v
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("platform version isn't supported")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := constants.VersionMap[info.Version]; ok {
|
if v, ok := constants.VersionMap[info.Version]; ok {
|
||||||
@@ -51,7 +57,13 @@ func (bvs BVSDecortClient) Check() (*CheckInfo, error) {
|
|||||||
|
|
||||||
err = json.Unmarshal([]byte(strings.Replace(strings.Trim(string(res), `"`), "\\", "", -1)), &info)
|
err = json.Unmarshal([]byte(strings.Replace(strings.Trim(string(res), `"`), "\\", "", -1)), &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
var v string
|
||||||
|
json.Unmarshal([]byte(res), &v)
|
||||||
|
if _, exists := constants.VersionMap[v]; exists {
|
||||||
|
info.Version = v
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("platform version isn't supported")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := constants.VersionMap[info.Version]; ok {
|
if v, ok := constants.VersionMap[info.Version]; ok {
|
||||||
@@ -74,7 +86,13 @@ func (ldc LegacyDecortClient) Check() (*CheckInfo, error) {
|
|||||||
|
|
||||||
err = json.Unmarshal([]byte(strings.Replace(strings.Trim(string(res), `"`), "\\", "", -1)), &info)
|
err = json.Unmarshal([]byte(strings.Replace(strings.Trim(string(res), `"`), "\\", "", -1)), &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
var v string
|
||||||
|
json.Unmarshal([]byte(res), &v)
|
||||||
|
if _, exists := constants.VersionMap[v]; exists {
|
||||||
|
info.Version = v
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("platform version isn't supported")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := constants.VersionMap[info.Version]; ok {
|
if v, ok := constants.VersionMap[info.Version]; ok {
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ func (dc *DecortClient) do(req *http.Request, ctype string) ([]byte, error) {
|
|||||||
|
|
||||||
// handle successful request
|
// handle successful request
|
||||||
respBytes, _ := io.ReadAll(resp.Body)
|
respBytes, _ := io.ReadAll(resp.Body)
|
||||||
if resp.StatusCode == 200 {
|
if resp.StatusCode == 200 || resp.StatusCode == 204 {
|
||||||
return respBytes, nil
|
return respBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BVSDecortClient is HTTP-client for platform
|
// BVSDecortClient is HTTP-client for platform
|
||||||
@@ -69,6 +70,11 @@ func (bdc *BVSDecortClient) CloudBroker() *cloudbroker.CloudBroker {
|
|||||||
return cloudbroker.New(bdc)
|
return cloudbroker.New(bdc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SDN builder
|
||||||
|
func (bdc *BVSDecortClient) SDN() *sdn.SDN {
|
||||||
|
return sdn.New(bdc)
|
||||||
|
}
|
||||||
|
|
||||||
// DecortApiCall method for sending requests to the platform
|
// DecortApiCall method for sending requests to the platform
|
||||||
func (bdc *BVSDecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
|
func (bdc *BVSDecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
|
||||||
var body *bytes.Buffer
|
var body *bytes.Buffer
|
||||||
|
|||||||
32
client_mock.go
Normal file
32
client_mock.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package decortsdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockDecortClient struct {
|
||||||
|
apiCaller *MockCaller
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMockDecortClient(apiCaller *MockCaller) ClientInterface {
|
||||||
|
return &MockDecortClient{
|
||||||
|
apiCaller: apiCaller,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloudAPI builder
|
||||||
|
func (mdc *MockDecortClient) CloudAPI() *cloudapi.CloudAPI {
|
||||||
|
return cloudapi.New(mdc.apiCaller)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloudBroker builder
|
||||||
|
func (mdc *MockDecortClient) CloudBroker() *cloudbroker.CloudBroker {
|
||||||
|
return cloudbroker.New(mdc.apiCaller)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDN builder
|
||||||
|
func (mdc *MockDecortClient) SDN() *sdn.SDN {
|
||||||
|
return sdn.New(mdc.apiCaller)
|
||||||
|
}
|
||||||
86
client_mock_gen.go
Normal file
86
client_mock_gen.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: interfaces/caller.go
|
||||||
|
//
|
||||||
|
// Generated by this command:
|
||||||
|
//
|
||||||
|
// mockgen -package decortsdk -source interfaces/caller.go
|
||||||
|
//
|
||||||
|
|
||||||
|
// Package decortsdk is a generated GoMock package.
|
||||||
|
package decortsdk
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
gomock "go.uber.org/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockCaller is a mock of Caller interface.
|
||||||
|
type MockCaller struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockCallerMockRecorder
|
||||||
|
isgomock struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockCallerMockRecorder is the mock recorder for MockCaller.
|
||||||
|
type MockCallerMockRecorder struct {
|
||||||
|
mock *MockCaller
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockCaller creates a new mock instance.
|
||||||
|
func NewMockCaller(ctrl *gomock.Controller) *MockCaller {
|
||||||
|
mock := &MockCaller{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockCallerMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockCaller) EXPECT() *MockCallerMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecortApiCall mocks base method.
|
||||||
|
func (m *MockCaller) DecortApiCall(ctx context.Context, method, url string, params any) ([]byte, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "DecortApiCall", ctx, method, url, params)
|
||||||
|
ret0, _ := ret[0].([]byte)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecortApiCall indicates an expected call of DecortApiCall.
|
||||||
|
func (mr *MockCallerMockRecorder) DecortApiCall(ctx, method, url, params any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecortApiCall", reflect.TypeOf((*MockCaller)(nil).DecortApiCall), ctx, method, url, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecortApiCallCtype mocks base method.
|
||||||
|
func (m *MockCaller) DecortApiCallCtype(ctx context.Context, method, url, ctype string, params any) ([]byte, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "DecortApiCallCtype", ctx, method, url, ctype, params)
|
||||||
|
ret0, _ := ret[0].([]byte)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecortApiCallCtype indicates an expected call of DecortApiCallCtype.
|
||||||
|
func (mr *MockCallerMockRecorder) DecortApiCallCtype(ctx, method, url, ctype, params any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecortApiCallCtype", reflect.TypeOf((*MockCaller)(nil).DecortApiCallCtype), ctx, method, url, ctype, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecortApiCallMP mocks base method.
|
||||||
|
func (m *MockCaller) DecortApiCallMP(ctx context.Context, method, url string, params any) ([]byte, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "DecortApiCallMP", ctx, method, url, params)
|
||||||
|
ret0, _ := ret[0].([]byte)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecortApiCallMP indicates an expected call of DecortApiCallMP.
|
||||||
|
func (mr *MockCallerMockRecorder) DecortApiCallMP(ctx, method, url, params any) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecortApiCallMP", reflect.TypeOf((*MockCaller)(nil).DecortApiCallMP), ctx, method, url, params)
|
||||||
|
}
|
||||||
18
go.mod
18
go.mod
@@ -1,21 +1,25 @@
|
|||||||
module repository.basistech.ru/BASIS/decort-golang-sdk
|
module repository.basistech.ru/BASIS/decort-golang-sdk
|
||||||
|
|
||||||
go 1.20
|
go 1.24.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-playground/validator/v10 v10.11.2
|
github.com/go-playground/validator/v10 v10.28.0
|
||||||
github.com/google/go-querystring v1.1.0
|
github.com/google/go-querystring v1.1.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
|
github.com/stretchr/testify v1.9.0
|
||||||
|
go.uber.org/mock v0.6.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
|
||||||
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/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
golang.org/x/crypto v0.15.0 // indirect
|
golang.org/x/crypto v0.42.0 // indirect
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.36.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.29.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
40
go.sum
40
go.sum
@@ -1,13 +1,15 @@
|
|||||||
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
|
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
|
||||||
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
|
||||||
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-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
@@ -15,26 +17,22 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
|
|||||||
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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
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/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/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||||
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 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
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.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=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -28,5 +28,9 @@ var FileName = map[string]string{
|
|||||||
var K8sValues = []string{"labels", "taints", "annotations, additionalSANs"}
|
var K8sValues = []string{"labels", "taints", "annotations, additionalSANs"}
|
||||||
|
|
||||||
var VersionMap = map[string]string{
|
var VersionMap = map[string]string{
|
||||||
|
"4.4.0": "-",
|
||||||
"4.3.0": "-",
|
"4.3.0": "-",
|
||||||
|
"4.2.0": "-",
|
||||||
|
"4.1.1": "-",
|
||||||
|
"4.1.0": "-",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,11 +165,11 @@ func flipgroupClientTypeValidator(fe validator.FieldLevel) bool {
|
|||||||
return IsInSlice(fieldValue, flipgroupClientTypeValues)
|
return IsInSlice(fieldValue, flipgroupClientTypeValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// kvmNetTypeValidator is used to validate NetType field.
|
// massCreateTypeValidator is used to validate net type field when mass creating kvm
|
||||||
func kvmNetTypeValidator(fe validator.FieldLevel) bool {
|
func massCreateTypeValidator(fe validator.FieldLevel) bool {
|
||||||
fieldValue := fe.Field().String()
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
return IsInSlice(fieldValue, kvmNetTypeValues)
|
return IsInSlice(fieldValue, massCreateNetTypeValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// lbAlgorithmValidator is used to validate Algorithm field.
|
// lbAlgorithmValidator is used to validate Algorithm field.
|
||||||
@@ -426,6 +426,13 @@ func deviceValidator(fe validator.FieldLevel) bool {
|
|||||||
return IsInSlice(fieldValue, deviceValues)
|
return IsInSlice(fieldValue, deviceValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ipTypesValidator is used to validate ip types version fields
|
||||||
|
func ipTypesValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return IsInSlice(fieldValue, ipTypeValues)
|
||||||
|
}
|
||||||
|
|
||||||
// ValidateRAM checks if request contains RAM value that is positive integer divisible by divisibility passed.
|
// ValidateRAM checks if request contains RAM value that is positive integer divisible by divisibility passed.
|
||||||
// It is recommended to pass constants.RAM_DIVISIBILITY as divisility arguement
|
// It is recommended to pass constants.RAM_DIVISIBILITY as divisility arguement
|
||||||
func ValidateRAM(r interfaces.RequestWithRAM, divisibility uint64) error {
|
func ValidateRAM(r interfaces.RequestWithRAM, divisibility uint64) error {
|
||||||
@@ -457,3 +464,10 @@ func trunkTagsValidator(fe validator.FieldLevel) bool {
|
|||||||
}
|
}
|
||||||
return uint64(numFieldValue) >= uint64(trunkTagsMin) && uint64(numFieldValue) <= uint64(trunkTagsMax)
|
return uint64(numFieldValue) >= uint64(trunkTagsMin) && uint64(numFieldValue) <= uint64(trunkTagsMax)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addressPoolNetTypeValidator is used to validate NetAddressType fields
|
||||||
|
func addressPoolNetTypeValidator(fe validator.FieldLevel) bool {
|
||||||
|
fieldValue := fe.Field().String()
|
||||||
|
|
||||||
|
return IsInSlice(fieldValue, addressPoolNetTypeValues)
|
||||||
|
}
|
||||||
|
|||||||
@@ -142,12 +142,12 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
prefix,
|
prefix,
|
||||||
fe.Field())
|
fe.Field())
|
||||||
|
|
||||||
// KVM_X86 Validators
|
// KVM_X86 Mass create validators
|
||||||
case "kvmNetType":
|
case "massCreateNetType":
|
||||||
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(kvmNetTypeValues))
|
joinValues(massCreateNetTypeValues))
|
||||||
|
|
||||||
// LB Validators
|
// LB Validators
|
||||||
case "lbAlgorithm":
|
case "lbAlgorithm":
|
||||||
@@ -348,11 +348,24 @@ func errorMessage(fe validator.FieldError) string {
|
|||||||
prefix,
|
prefix,
|
||||||
fe.Field())
|
fe.Field())
|
||||||
|
|
||||||
|
// addressPoolNetTypeValidator validator
|
||||||
|
case "addressPoolNetTypeValidator":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(addressPoolNetTypeValues))
|
||||||
|
|
||||||
case "device":
|
case "device":
|
||||||
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(deviceValues))
|
joinValues(deviceValues))
|
||||||
|
|
||||||
|
case "ipTypes":
|
||||||
|
return fmt.Sprintf("%s %s must be one of the following: %s",
|
||||||
|
prefix,
|
||||||
|
fe.Field(),
|
||||||
|
joinValues(ipTypeValues))
|
||||||
}
|
}
|
||||||
|
|
||||||
return fe.Error()
|
return fe.Error()
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ func registerAllValidators(validate *validator.Validate) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = validate.RegisterValidation("kvmNetType", kvmNetTypeValidator)
|
err = validate.RegisterValidation("massCreateNetType", massCreateTypeValidator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -301,5 +301,15 @@ func registerAllValidators(validate *validator.Validate) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("addressPoolNetTypeValidator", addressPoolNetTypeValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = validate.RegisterValidation("ipTypes", ipTypesValidator)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ var (
|
|||||||
|
|
||||||
flipgroupClientTypeValues = []string{"compute", "vins"}
|
flipgroupClientTypeValues = []string{"compute", "vins"}
|
||||||
|
|
||||||
kvmNetTypeValues = []string{"EXTNET", "VINS", "NONE"}
|
massCreateNetTypeValues = []string{"EXTNET", "VINS", "TRUNK"}
|
||||||
kvmx86NetTypeValues = []string{"EXTNET", "VINS", "EMPTY", "VFNIC", "DPDK", "SDN", "TRUNK"}
|
kvmx86NetTypeValues = []string{"EXTNET", "VINS", "EMPTY", "VFNIC", "DPDK", "SDN", "TRUNK"}
|
||||||
|
|
||||||
lbAlgorithmValues = []string{"roundrobin", "static-rr", "leastconn"}
|
lbAlgorithmValues = []string{"roundrobin", "static-rr", "leastconn"}
|
||||||
@@ -77,6 +77,10 @@ var (
|
|||||||
securityGroupDirectionValues = []string{"inbound", "outbound"}
|
securityGroupDirectionValues = []string{"inbound", "outbound"}
|
||||||
securityGroupEthertypeValues = []string{"IPv4", "IPv6"}
|
securityGroupEthertypeValues = []string{"IPv4", "IPv6"}
|
||||||
securityGroupProtocolValues = []string{"icmp", "tcp", "udp"}
|
securityGroupProtocolValues = []string{"icmp", "tcp", "udp"}
|
||||||
|
|
||||||
|
addressPoolNetTypeValues = []string{"IPv4", "IPv6", "MAC"}
|
||||||
|
|
||||||
|
ipTypeValues = []string{"v4, v6"}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LegacyDecortClient is Legacy HTTP-client for platform
|
// LegacyDecortClient is Legacy HTTP-client for platform
|
||||||
@@ -67,6 +68,11 @@ func (ldc *LegacyDecortClient) CloudBroker() *cloudbroker.CloudBroker {
|
|||||||
return cloudbroker.New(ldc)
|
return cloudbroker.New(ldc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SDN builder
|
||||||
|
func (ldc *LegacyDecortClient) SDN() *sdn.SDN {
|
||||||
|
return sdn.New(ldc)
|
||||||
|
}
|
||||||
|
|
||||||
// DecortApiCall method for sending requests to the platform
|
// DecortApiCall method for sending requests to the platform
|
||||||
func (ldc *LegacyDecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
|
func (ldc *LegacyDecortClient) DecortApiCall(ctx context.Context, method, url string, params interface{}) ([]byte, error) {
|
||||||
// get token
|
// get token
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type ChangeSecGroupsRequest struct {
|
|||||||
|
|
||||||
// Flag indicating whether security groups are enabled for this interface
|
// Flag indicating whether security groups are enabled for this interface
|
||||||
// Required: false
|
// Required: false
|
||||||
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
|
EnableSecGroups interface{} `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty" validate:"omitempty,isBool"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeSecGroups changes security groups for compute
|
// ChangeSecGroups changes security groups for compute
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package compute
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +18,10 @@ type CloneRequest struct {
|
|||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name" validate:"required"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the Storage Policy
|
||||||
|
// Required: true
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
|
||||||
|
|
||||||
// Timestamp of the parent's snapshot to create clone from
|
// Timestamp of the parent's snapshot to create clone from
|
||||||
// Required: false
|
// Required: false
|
||||||
SnapshotTimestamp uint64 `url:"snapshotTimestamp,omitempty" json:"snapshotTimestamp,omitempty"`
|
SnapshotTimestamp uint64 `url:"snapshotTimestamp,omitempty" json:"snapshotTimestamp,omitempty"`
|
||||||
@@ -30,26 +34,29 @@ type CloneRequest struct {
|
|||||||
// Default: false
|
// Default: false
|
||||||
// Required: false
|
// Required: false
|
||||||
Force bool `url:"force" json:"force"`
|
Force bool `url:"force" json:"force"`
|
||||||
|
|
||||||
|
// The name of the pool to migrate disks to
|
||||||
|
// Required: false
|
||||||
|
PoolName string `url:"pool_name" json:"pool_name"`
|
||||||
|
|
||||||
|
// The ID of the SEP to migrate disks to
|
||||||
|
// Required: false
|
||||||
|
SEPID uint64 `url:"sep_id" json:"sep_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone clones compute instance
|
// Clone clones compute instance
|
||||||
func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) {
|
func (c Compute) Clone(ctx context.Context, req CloneRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, validators.ValidationErrors(validators.GetErrors(err))
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudapi/compute/clone"
|
url := "/cloudapi/compute/clone"
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseUint(string(res), 10, 64)
|
return string(res), nil
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
39
pkg/cloudapi/compute/clone_abort.go
Normal file
39
pkg/cloudapi/compute/clone_abort.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CloneAbortRequest struct to abort a compute clone
|
||||||
|
type CloneAbortRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneAbort aborts a compute clone
|
||||||
|
func (c Compute) CloneAbort(ctx context.Context, req CloneAbortRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/compute/clone_abort"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.ParseBool(string(res))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
40
pkg/cloudapi/compute/clone_status.go
Normal file
40
pkg/cloudapi/compute/clone_status.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetCloneStatusRequest struct to get information about compute clone status
|
||||||
|
type GetCloneStatusRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCloneStatus gets information about compute clone status as a RecordCloneStatus struct
|
||||||
|
func (c Compute) GetCloneStatus(ctx context.Context, req GetCloneStatusRequest) ([]RecordCloneStatus, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/compute/clone_status"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneStatus := make([]RecordCloneStatus, 0)
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &cloneStatus)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloneStatus, nil
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package compute
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
@@ -27,47 +26,15 @@ type wrapperCreateTemplateRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplate create template from compute instance
|
// CreateTemplate create template from compute instance
|
||||||
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (uint64, error) {
|
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
return 0, validators.ValidationErrors(validators.GetErrors(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
reqWrapped := wrapperCreateTemplateRequest{
|
|
||||||
CreateTemplateRequest: req,
|
|
||||||
AsyncMode: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "/cloudapi/compute/createTemplate"
|
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := strconv.ParseUint(string(res), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateTemplateAsync create template from compute instance
|
|
||||||
func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", validators.ValidationErrors(validators.GetErrors(err))
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
reqWrapped := wrapperCreateTemplateRequest{
|
|
||||||
CreateTemplateRequest: req,
|
|
||||||
AsyncMode: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "/cloudapi/compute/createTemplate"
|
url := "/cloudapi/compute/createTemplate"
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,6 +161,9 @@ type RecordAffinityRelations struct {
|
|||||||
|
|
||||||
// Main information about attached network
|
// Main information about attached network
|
||||||
type RecordNetAttach struct {
|
type RecordNetAttach struct {
|
||||||
|
// Bus number
|
||||||
|
BusNumber uint64 `json:"bus_number"`
|
||||||
|
|
||||||
// Connection ID
|
// Connection ID
|
||||||
ConnID uint64 `json:"connId"`
|
ConnID uint64 `json:"connId"`
|
||||||
|
|
||||||
@@ -173,6 +176,9 @@ type RecordNetAttach struct {
|
|||||||
// Enabled
|
// Enabled
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Enable security groups
|
||||||
|
EnableSecGroups bool `json:"enable_secgroups"`
|
||||||
|
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
FLIPGroupID uint64 `json:"flipgroupId"`
|
FLIPGroupID uint64 `json:"flipgroupId"`
|
||||||
|
|
||||||
@@ -182,12 +188,18 @@ type RecordNetAttach struct {
|
|||||||
// IP address
|
// IP address
|
||||||
IPAddress string `json:"ipAddress"`
|
IPAddress string `json:"ipAddress"`
|
||||||
|
|
||||||
|
// Libvirt Settings
|
||||||
|
LibvirtSettings LibvirtSettings `json:"libvirtSettings"`
|
||||||
|
|
||||||
// Listen SSH
|
// Listen SSH
|
||||||
ListenSSH bool `json:"listenSsh"`
|
ListenSSH bool `json:"listenSsh"`
|
||||||
|
|
||||||
// MAC
|
// MAC
|
||||||
MAC string `json:"mac"`
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// Maximum transmission unit
|
||||||
|
MTU uint64 `json:"mtu"`
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
@@ -200,9 +212,18 @@ type RecordNetAttach struct {
|
|||||||
// Network type
|
// Network type
|
||||||
NetType string `json:"netType"`
|
NetType string `json:"netType"`
|
||||||
|
|
||||||
|
// Node id
|
||||||
|
NodeID int `json:"nodeId"`
|
||||||
|
|
||||||
// PCI slot
|
// PCI slot
|
||||||
PCISlot int64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
|
// SDN interface ID
|
||||||
|
SDNInterfaceID string `json:"sdn_interface_id"`
|
||||||
|
|
||||||
|
// List of security groups
|
||||||
|
SecurityGroups []uint64 `json:"security_groups"`
|
||||||
|
|
||||||
// QOS
|
// QOS
|
||||||
QOS QOS `json:"qos"`
|
QOS QOS `json:"qos"`
|
||||||
|
|
||||||
@@ -212,11 +233,11 @@ type RecordNetAttach struct {
|
|||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// List of trunk tags
|
||||||
|
TrunkTags []uint64 `json:"trunk_tags"`
|
||||||
|
|
||||||
// List VNF IDs
|
// List VNF IDs
|
||||||
VNFs []uint64 `json:"vnfs"`
|
VNFs []uint64 `json:"vnfs"`
|
||||||
|
|
||||||
// Maximum transmission unit
|
|
||||||
MTU uint64 `json:"mtu"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detailed information about audit
|
// Detailed information about audit
|
||||||
@@ -311,6 +332,9 @@ type RecordCompute struct {
|
|||||||
// Architecture
|
// Architecture
|
||||||
Architecture string `json:"arch"`
|
Architecture string `json:"arch"`
|
||||||
|
|
||||||
|
// Boot image ID
|
||||||
|
BootImageID uint64 `json:"boot_image_id"`
|
||||||
|
|
||||||
// Boot order
|
// Boot order
|
||||||
BootOrder []string `json:"bootOrder"`
|
BootOrder []string `json:"bootOrder"`
|
||||||
|
|
||||||
@@ -1013,6 +1037,9 @@ type ItemCompute struct {
|
|||||||
// Architecture
|
// Architecture
|
||||||
Architecture string `json:"arch"`
|
Architecture string `json:"arch"`
|
||||||
|
|
||||||
|
// Boot image ID
|
||||||
|
BootImageID uint64 `json:"boot_image_id"`
|
||||||
|
|
||||||
// Boot order
|
// Boot order
|
||||||
BootOrder []string `json:"bootOrder"`
|
BootOrder []string `json:"bootOrder"`
|
||||||
|
|
||||||
@@ -1322,3 +1349,31 @@ type ListPCIDevices struct {
|
|||||||
// Entry count
|
// Entry count
|
||||||
EntryCount uint64 `json:"entryCount"`
|
EntryCount uint64 `json:"entryCount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RecordCloneStatus struct {
|
||||||
|
// Disk ID
|
||||||
|
DiskID int `json:"disk_id"`
|
||||||
|
|
||||||
|
// Clone Status
|
||||||
|
Status CloneStatus `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CloneStatus struct {
|
||||||
|
// Type
|
||||||
|
Type int `json:"type"`
|
||||||
|
|
||||||
|
// Copy speed
|
||||||
|
Bandwidth int `json:"bandwidth"`
|
||||||
|
|
||||||
|
// Current progress
|
||||||
|
Cur int `json:"cur"`
|
||||||
|
|
||||||
|
// Total size
|
||||||
|
End int `json:"end"`
|
||||||
|
|
||||||
|
// Operation status
|
||||||
|
Ready bool `json:"ready"`
|
||||||
|
|
||||||
|
// Progress percent
|
||||||
|
ProgressPercent int `json:"progress_percent"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ type RecordImage struct {
|
|||||||
// Tech status
|
// Tech status
|
||||||
TechStatus string `json:"techStatus"`
|
TechStatus string `json:"techStatus"`
|
||||||
|
|
||||||
|
// Need to clean before destroy
|
||||||
|
ToClean bool `json:"to_clean"`
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
|||||||
46
pkg/cloudapi/rg/add_storage_policy.go
Normal file
46
pkg/cloudapi/rg/add_storage_policy.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package rg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AddStoragePolicyRequest struct for adding storage policy to the resource group
|
||||||
|
type AddStoragePolicyRequest struct {
|
||||||
|
// ID of resource group to add to
|
||||||
|
// Required: true
|
||||||
|
RGID uint64 `url:"resgroup_id" json:"resgroup_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the storage policy to which to connect resource group
|
||||||
|
// Required: true
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
|
||||||
|
|
||||||
|
// Limit storage resources GB. Or -1 unlimit
|
||||||
|
// Required: false
|
||||||
|
Limit int `url:"limit,omitempty" json:"limit,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddStoragePolicy add storage policy to the account.
|
||||||
|
func (r RG) AddStoragePolicy(ctx context.Context, req AddStoragePolicyRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/rg/add_storage_policy"
|
||||||
|
|
||||||
|
res, err := r.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
|
||||||
|
}
|
||||||
42
pkg/cloudapi/rg/del_storage_policy.go
Normal file
42
pkg/cloudapi/rg/del_storage_policy.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package rg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DelStoragePolicyRequest struct for deleting storage policy to the resource group
|
||||||
|
type DelStoragePolicyRequest struct {
|
||||||
|
// ID of resource group
|
||||||
|
// Required: true
|
||||||
|
RGID uint64 `url:"resgroup_id" json:"resgroup_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the storage policy to which to disconnect account
|
||||||
|
// Required: true
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DelStoragePolicy delete storage policy to the account.
|
||||||
|
func (r RG) DelStoragePolicy(ctx context.Context, req DelStoragePolicyRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/rg/del_storage_policy"
|
||||||
|
|
||||||
|
res, err := r.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.ParseBool(string(res))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -30,6 +30,9 @@ type ItemStoragePolicy struct {
|
|||||||
// Max IOPS for the sotrage policy
|
// Max IOPS for the sotrage policy
|
||||||
LimitIOPS uint64 `json:"limit_iops"`
|
LimitIOPS uint64 `json:"limit_iops"`
|
||||||
|
|
||||||
|
// Storage policy ID
|
||||||
|
StoragePolicyID uint64 `json:"storage_policy_id"`
|
||||||
|
|
||||||
// Which accounts and resource groups use the storage policy
|
// Which accounts and resource groups use the storage policy
|
||||||
Usage Usage `json:"usage"`
|
Usage Usage `json:"usage"`
|
||||||
}
|
}
|
||||||
@@ -56,6 +59,9 @@ type InfoStoragePolicy struct {
|
|||||||
// Max IOPS for the sotrage policy
|
// Max IOPS for the sotrage policy
|
||||||
LimitIOPS uint64 `json:"limit_iops"`
|
LimitIOPS uint64 `json:"limit_iops"`
|
||||||
|
|
||||||
|
// ID of the storage policy
|
||||||
|
StoragePolicyID uint64 `json:"storage_policy_id"`
|
||||||
|
|
||||||
// Which accounts and resource groups use the storage policy
|
// Which accounts and resource groups use the storage policy
|
||||||
Usage Usage `json:"usage"`
|
Usage Usage `json:"usage"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,6 +214,9 @@ type RecordVNFDev struct {
|
|||||||
|
|
||||||
// Zone ID
|
// Zone ID
|
||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
|
|
||||||
|
// Live migration job ID
|
||||||
|
LiveMigrationJobID uint64 `json:"live_migration_job_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VNF config
|
// VNF config
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ type ChangeSecGroupsRequest struct {
|
|||||||
|
|
||||||
// Flag indicating whether security groups are enabled for this interface
|
// Flag indicating whether security groups are enabled for this interface
|
||||||
// Required: false
|
// Required: false
|
||||||
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
|
EnableSecGroups interface{} `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty" validate:"omitempty,isBool"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangeSecGroups changes security groups for compute
|
// ChangeSecGroups changes security groups for compute
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package compute
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +18,10 @@ type CloneRequest struct {
|
|||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name" validate:"required"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the Storage Policy
|
||||||
|
// Required: true
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id" json:"storage_policy_id" validate:"required"`
|
||||||
|
|
||||||
// Timestamp of the parent's snapshot to create clone from
|
// Timestamp of the parent's snapshot to create clone from
|
||||||
// Required: false
|
// Required: false
|
||||||
SnapshotTimestamp uint64 `url:"snapshotTimestamp" json:"snapshotTimestamp"`
|
SnapshotTimestamp uint64 `url:"snapshotTimestamp" json:"snapshotTimestamp"`
|
||||||
@@ -30,26 +34,29 @@ type CloneRequest struct {
|
|||||||
// Default: false
|
// Default: false
|
||||||
// Required: false
|
// Required: false
|
||||||
Force bool `url:"force" json:"force"`
|
Force bool `url:"force" json:"force"`
|
||||||
|
|
||||||
|
// The name of the pool to migrate disks to
|
||||||
|
// Required: false
|
||||||
|
PoolName string `url:"pool_name" json:"pool_name"`
|
||||||
|
|
||||||
|
// The ID of the SEP to migrate disks to
|
||||||
|
// Required: false
|
||||||
|
SEPID uint64 `url:"sep_id" json:"sep_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone clones compute instance
|
// Clone clones compute instance
|
||||||
func (c Compute) Clone(ctx context.Context, req CloneRequest) (uint64, error) {
|
func (c Compute) Clone(ctx context.Context, req CloneRequest) (string, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, validators.ValidationErrors(validators.GetErrors(err))
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/cloudbroker/compute/clone"
|
url := "/cloudbroker/compute/clone"
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := strconv.ParseUint(string(res), 10, 64)
|
return string(res), nil
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
39
pkg/cloudbroker/compute/clone_abort.go
Normal file
39
pkg/cloudbroker/compute/clone_abort.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CloneAbortRequest struct to abort a compute clone
|
||||||
|
type CloneAbortRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloneAbort aborts a compute clone
|
||||||
|
func (c Compute) CloneAbort(ctx context.Context, req CloneAbortRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/clone_abort"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.ParseBool(string(res))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
40
pkg/cloudbroker/compute/clone_status.go
Normal file
40
pkg/cloudbroker/compute/clone_status.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetCloneStatusRequest struct to get information about compute clone status
|
||||||
|
type GetCloneStatusRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCloneStatus gets information about compute clone status as a RecordCloneStatus struct
|
||||||
|
func (c Compute) GetCloneStatus(ctx context.Context, req GetCloneStatusRequest) ([]RecordCloneStatus, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/clone_status"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneStatus := make([]RecordCloneStatus, 0)
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &cloneStatus)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloneStatus, nil
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package compute
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
@@ -20,27 +19,16 @@ type CreateTemplateRequest struct {
|
|||||||
Name string `url:"name" json:"name" validate:"required"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type wrapperCreateTemplateRequest struct {
|
// CreateTemplate create template from compute instance
|
||||||
CreateTemplateRequest
|
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
||||||
|
|
||||||
AsyncMode bool `url:"asyncMode"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateTemplateAsync create template from compute instance
|
|
||||||
func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequest) (string, error) {
|
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", validators.ValidationErrors(validators.GetErrors(err))
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
reqWrapped := wrapperCreateTemplateRequest{
|
|
||||||
CreateTemplateRequest: req,
|
|
||||||
AsyncMode: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "/cloudbroker/compute/createTemplate"
|
url := "/cloudbroker/compute/createTemplate"
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -49,30 +37,3 @@ func (c Compute) CreateTemplateAsync(ctx context.Context, req CreateTemplateRequ
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTemplate create template from compute instance
|
|
||||||
func (c Compute) CreateTemplate(ctx context.Context, req CreateTemplateRequest) (uint64, error) {
|
|
||||||
err := validators.ValidateRequest(req)
|
|
||||||
if err != nil {
|
|
||||||
return 0, validators.ValidationErrors(validators.GetErrors(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
reqWrapped := wrapperCreateTemplateRequest{
|
|
||||||
CreateTemplateRequest: req,
|
|
||||||
AsyncMode: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
url := "/cloudbroker/compute/createTemplate"
|
|
||||||
|
|
||||||
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := strconv.ParseUint(string(res), 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -127,6 +127,9 @@ type QOS struct {
|
|||||||
|
|
||||||
// Main information about attached network
|
// Main information about attached network
|
||||||
type RecordNetAttach struct {
|
type RecordNetAttach struct {
|
||||||
|
// Bus number
|
||||||
|
BusNumber uint64 `json:"bus_number"`
|
||||||
|
|
||||||
// Connection ID
|
// Connection ID
|
||||||
ConnID uint64 `json:"connId"`
|
ConnID uint64 `json:"connId"`
|
||||||
|
|
||||||
@@ -139,6 +142,9 @@ type RecordNetAttach struct {
|
|||||||
// Enabled
|
// Enabled
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Enable security groups
|
||||||
|
EnableSecGroups bool `json:"enable_secgroups"`
|
||||||
|
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
FLIPGroupID uint64 `json:"flipgroupId"`
|
FLIPGroupID uint64 `json:"flipgroupId"`
|
||||||
|
|
||||||
@@ -148,12 +154,18 @@ type RecordNetAttach struct {
|
|||||||
// IP address
|
// IP address
|
||||||
IPAddress string `json:"ipAddress"`
|
IPAddress string `json:"ipAddress"`
|
||||||
|
|
||||||
|
// Libvirt Settings
|
||||||
|
LibvirtSettings LibvirtSettings `json:"libvirtSettings"`
|
||||||
|
|
||||||
// Listen SSH
|
// Listen SSH
|
||||||
ListenSSH bool `json:"listenSsh"`
|
ListenSSH bool `json:"listenSsh"`
|
||||||
|
|
||||||
// MAC
|
// MAC
|
||||||
MAC string `json:"mac"`
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// Maximum transmission unit
|
||||||
|
MTU uint64 `json:"mtu"`
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
@@ -166,9 +178,18 @@ type RecordNetAttach struct {
|
|||||||
// Network type
|
// Network type
|
||||||
NetType string `json:"netType"`
|
NetType string `json:"netType"`
|
||||||
|
|
||||||
|
// Node id
|
||||||
|
NodeID int `json:"nodeId"`
|
||||||
|
|
||||||
// PCI slot
|
// PCI slot
|
||||||
PCISlot int64 `json:"pciSlot"`
|
PCISlot int64 `json:"pciSlot"`
|
||||||
|
|
||||||
|
// SDN interface ID
|
||||||
|
SDNInterfaceID string `json:"sdn_interface_id"`
|
||||||
|
|
||||||
|
// List of security groups
|
||||||
|
SecurityGroups []uint64 `json:"security_groups"`
|
||||||
|
|
||||||
// QOS
|
// QOS
|
||||||
QOS QOS `json:"qos"`
|
QOS QOS `json:"qos"`
|
||||||
|
|
||||||
@@ -178,6 +199,9 @@ type RecordNetAttach struct {
|
|||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// List of trunk tags
|
||||||
|
TrunkTags []uint64 `json:"trunk_tags"`
|
||||||
|
|
||||||
// List VNF IDs
|
// List VNF IDs
|
||||||
VNFs []uint64 `json:"vnfs"`
|
VNFs []uint64 `json:"vnfs"`
|
||||||
}
|
}
|
||||||
@@ -663,6 +687,9 @@ type InfoCompute struct {
|
|||||||
// Architecture
|
// Architecture
|
||||||
Arch string `json:"arch"`
|
Arch string `json:"arch"`
|
||||||
|
|
||||||
|
// Boot image ID
|
||||||
|
BootImageID uint64 `json:"boot_image_id"`
|
||||||
|
|
||||||
// Boot order
|
// Boot order
|
||||||
BootOrder []string `json:"bootOrder"`
|
BootOrder []string `json:"bootOrder"`
|
||||||
|
|
||||||
@@ -917,6 +944,9 @@ type RecordCompute struct {
|
|||||||
// Architecture
|
// Architecture
|
||||||
Arch string `json:"arch"`
|
Arch string `json:"arch"`
|
||||||
|
|
||||||
|
// Boot image ID
|
||||||
|
BootImageID uint64 `json:"boot_image_id"`
|
||||||
|
|
||||||
// Boot order
|
// Boot order
|
||||||
BootOrder []string `json:"bootOrder"`
|
BootOrder []string `json:"bootOrder"`
|
||||||
|
|
||||||
@@ -1420,3 +1450,31 @@ type MigrateStorageItem struct {
|
|||||||
// Target stack ID
|
// Target stack ID
|
||||||
TargetStackID uint64 `json:"targetStackId"`
|
TargetStackID uint64 `json:"targetStackId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RecordCloneStatus struct {
|
||||||
|
// Disk ID
|
||||||
|
DiskID int `json:"disk_id"`
|
||||||
|
|
||||||
|
// Clone Status
|
||||||
|
Status CloneStatus `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CloneStatus struct {
|
||||||
|
// Type
|
||||||
|
Type int `json:"type"`
|
||||||
|
|
||||||
|
// Copy speed
|
||||||
|
Bandwidth int `json:"bandwidth"`
|
||||||
|
|
||||||
|
// Current progress
|
||||||
|
Cur int `json:"cur"`
|
||||||
|
|
||||||
|
// Total size
|
||||||
|
End int `json:"end"`
|
||||||
|
|
||||||
|
// Operation status
|
||||||
|
Ready bool `json:"ready"`
|
||||||
|
|
||||||
|
// Progress percent
|
||||||
|
ProgressPercent int `json:"progress_percent"`
|
||||||
|
}
|
||||||
|
|||||||
46
pkg/cloudbroker/disks/migrate.go
Normal file
46
pkg/cloudbroker/disks/migrate.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package disks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Migrate struct to move disk to another sep, pool and storage policy
|
||||||
|
type MigrateRequest struct {
|
||||||
|
// ID of the disk
|
||||||
|
// Required: true
|
||||||
|
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the new SEP
|
||||||
|
// Required: true
|
||||||
|
SEPID uint64 `url:"sep_id" json:"sep_id" validate:"required"`
|
||||||
|
|
||||||
|
// New pool name
|
||||||
|
// Required: true
|
||||||
|
PoolName string `url:"pool_name" json:"pool_name" validate:"required"`
|
||||||
|
|
||||||
|
// ID if the storage policy
|
||||||
|
// Required: false
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move moves disk to another sep, pool and storage policy
|
||||||
|
func (c Disks) Migrate(ctx context.Context, req MigrateRequest) (string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/disks/migrate"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := string(res)
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
38
pkg/cloudbroker/disks/migrate_abort.go
Normal file
38
pkg/cloudbroker/disks/migrate_abort.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package disks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MigrateAbortRequest struct to abort migration
|
||||||
|
type MigrateAbortRequest struct {
|
||||||
|
// ID of the disk
|
||||||
|
// Required: true
|
||||||
|
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// MigrateAbort aborts disk migration
|
||||||
|
func (c Disks) MigrateAbort(ctx context.Context, req MigrateAbortRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/disks/migrate_abort"
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
40
pkg/cloudbroker/disks/migrate_status.go
Normal file
40
pkg/cloudbroker/disks/migrate_status.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package disks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetMigrateStatusRequest struct to get information about disk migrate status
|
||||||
|
type GetMigrateStatusRequest struct {
|
||||||
|
// ID of disk
|
||||||
|
// Required: true
|
||||||
|
DiskID uint64 `url:"disk_id" json:"disk_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetMigrateStatus gets information about disk migrate status
|
||||||
|
func (c Disks) GetMigrateStatus(ctx context.Context, req GetMigrateStatusRequest) (*MigrateStatus, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/disks/migrate_status"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
status := MigrateStatus{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &status)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &status, nil
|
||||||
|
}
|
||||||
@@ -320,3 +320,20 @@ type ListTypes struct {
|
|||||||
// Entry count
|
// Entry count
|
||||||
EntryCount uint64 `json:"entryCount"`
|
EntryCount uint64 `json:"entryCount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MigrateStatus struct {
|
||||||
|
// Type
|
||||||
|
Type int `json:"type"`
|
||||||
|
|
||||||
|
// Copy speed
|
||||||
|
Bandwidth int `json:"bandwidth"`
|
||||||
|
|
||||||
|
// Current progress
|
||||||
|
Cur interface{} `json:"cur"`
|
||||||
|
|
||||||
|
// Total size
|
||||||
|
End interface{} `json:"end"`
|
||||||
|
|
||||||
|
// Progress percent
|
||||||
|
ProgressPercent int `json:"progress_percent"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package image
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@@ -43,6 +44,11 @@ type CreateCDROMImageRequest struct {
|
|||||||
PasswordDl string `url:"passwordDL,omitempty" json:"passwordDL,omitempty"`
|
PasswordDl string `url:"passwordDL,omitempty" json:"passwordDL,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type asyncWrapperCreateCDROMImageRequest struct {
|
||||||
|
CreateCDROMImageRequest
|
||||||
|
AsyncMode bool `url:"asyncMode"`
|
||||||
|
}
|
||||||
|
|
||||||
// CreateCDROMImage creates CD-ROM image from an ISO identified by URL
|
// CreateCDROMImage creates CD-ROM image from an ISO identified by URL
|
||||||
func (i Image) CreateCDROMImage(ctx context.Context, req CreateCDROMImageRequest) (uint64, error) {
|
func (i Image) CreateCDROMImage(ctx context.Context, req CreateCDROMImageRequest) (uint64, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
@@ -52,7 +58,9 @@ func (i Image) CreateCDROMImage(ctx context.Context, req CreateCDROMImageRequest
|
|||||||
|
|
||||||
url := "/cloudbroker/image/createCDROMImage"
|
url := "/cloudbroker/image/createCDROMImage"
|
||||||
|
|
||||||
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
syncReq := asyncWrapperCreateCDROMImageRequest{CreateCDROMImageRequest: req, AsyncMode: false}
|
||||||
|
|
||||||
|
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, syncReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@@ -64,3 +72,29 @@ func (i Image) CreateCDROMImage(ctx context.Context, req CreateCDROMImageRequest
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AsyncCreateCDROMImage creates CD-ROM image from an ISO identified by URL in async mode
|
||||||
|
func (i Image) AsyncCreateCDROMImage(ctx context.Context, req CreateCDROMImageRequest) (string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/image/createCDROMImage"
|
||||||
|
|
||||||
|
asyncReq := asyncWrapperCreateCDROMImageRequest{CreateCDROMImageRequest: req, AsyncMode: true}
|
||||||
|
|
||||||
|
res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, asyncReq)
|
||||||
|
if err != nil {
|
||||||
|
return " ", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var taskID string
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &taskID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return taskID, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// CreateRequest struct to create image
|
// CreateRequest struct to create image
|
||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
// Name of the rescue disk
|
// Name of the image
|
||||||
// Required: true
|
// Required: true
|
||||||
Name string `url:"name" json:"name" validate:"required"`
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,9 @@ type RecordImage struct {
|
|||||||
// Tech status
|
// Tech status
|
||||||
TechStatus string `json:"techStatus"`
|
TechStatus string `json:"techStatus"`
|
||||||
|
|
||||||
|
// Need to clean before destroy
|
||||||
|
ToClean bool `json:"to_clean"`
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
@@ -245,6 +248,9 @@ type ItemImage struct {
|
|||||||
// Tech status
|
// Tech status
|
||||||
TechStatus string `json:"techStatus"`
|
TechStatus string `json:"techStatus"`
|
||||||
|
|
||||||
|
// Need to clean before destroy
|
||||||
|
ToClean bool `json:"to_clean"`
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ type Interface struct {
|
|||||||
// - TRUNK
|
// - TRUNK
|
||||||
NetType string `url:"netType" json:"netType" validate:"required,kvmx86NetType"`
|
NetType string `url:"netType" json:"netType" validate:"required,kvmx86NetType"`
|
||||||
|
|
||||||
// Network ID for connect to,
|
// Network ID for connect
|
||||||
// for EXTNET - external network ID,
|
|
||||||
// for VINS - VINS ID,
|
|
||||||
NetID uint64 `url:"netId" json:"netId" validate:"required"`
|
NetID uint64 `url:"netId" json:"netId" validate:"required"`
|
||||||
|
|
||||||
// IP address to assign to this VM when connecting to the specified network
|
// IP address to assign to this VM when connecting to the specified network
|
||||||
|
|||||||
@@ -8,6 +8,47 @@ import (
|
|||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type InterfaceMassCreate struct {
|
||||||
|
// Network type
|
||||||
|
// Should be one of:
|
||||||
|
// - VINS
|
||||||
|
// - EXTNET
|
||||||
|
// - TRUNK
|
||||||
|
NetType string `url:"netType" json:"netType" validate:"required,massCreateNetType"`
|
||||||
|
|
||||||
|
// Network ID for connect
|
||||||
|
NetID uint64 `url:"netId" json:"netId" validate:"required"`
|
||||||
|
|
||||||
|
// IP address to assign to this VM when connecting to the specified network
|
||||||
|
// Required: false
|
||||||
|
IPAddr string `url:"ipAddr,omitempty" json:"ipAddr,omitempty"`
|
||||||
|
|
||||||
|
// Maximum transmission unit, must be 1-9216
|
||||||
|
// Used only to DPDK net type
|
||||||
|
// Required: false
|
||||||
|
MTU uint64 `url:"mtu,omitempty" json:"mtu,omitempty" validate:"omitempty,mtu"`
|
||||||
|
|
||||||
|
// MAC address to assign to this VM when connecting to the specified network
|
||||||
|
// Required: false
|
||||||
|
MAC string `url:"mac,omitempty" json:"mac,omitempty" validate:"omitempty"`
|
||||||
|
|
||||||
|
// SDN interface id
|
||||||
|
// Required: false
|
||||||
|
SDNInterfaceID string `url:"sdn_interface_id,omitempty" json:"sdn_interface_id,omitempty"`
|
||||||
|
|
||||||
|
// List of security group IDs to assign to this interface
|
||||||
|
// Required: false
|
||||||
|
SecGroups []uint64 `url:"security_groups,omitempty" json:"security_groups,omitempty"`
|
||||||
|
|
||||||
|
// Flag indicating whether security groups are enabled for this interface
|
||||||
|
// Required: false
|
||||||
|
EnableSecGroups bool `url:"enable_secgroups,omitempty" json:"enable_secgroups,omitempty"`
|
||||||
|
|
||||||
|
// Flag indicating whether this interface is enabled (only for VINS, EXTNET, DPDK, SDN, TRUNK)
|
||||||
|
// Required: false
|
||||||
|
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
||||||
|
}
|
||||||
|
|
||||||
// MassCreateRequest struct to mass create KVM x86
|
// MassCreateRequest struct to mass create KVM x86
|
||||||
type MassCreateRequest struct {
|
type MassCreateRequest struct {
|
||||||
// ID of the resource group, which will own this VM
|
// ID of the resource group, which will own this VM
|
||||||
@@ -66,7 +107,7 @@ type MassCreateRequest struct {
|
|||||||
// If not specified, compute will be created with default interface from RG.
|
// If not specified, compute will be created with default interface from RG.
|
||||||
// To create compute without interfaces, pass initialized empty slice .
|
// To create compute without interfaces, pass initialized empty slice .
|
||||||
// Required: false
|
// Required: false
|
||||||
Interfaces []Interface `url:"-" json:"interfaces,omitempty" validate:"omitempty,dive"`
|
Interfaces []InterfaceMassCreate `url:"-" json:"interfaces,omitempty" validate:"omitempty,dive"`
|
||||||
|
|
||||||
// Input data for cloud-init facility
|
// Input data for cloud-init facility
|
||||||
// Required: false
|
// Required: false
|
||||||
|
|||||||
42
pkg/cloudbroker/node/update_description.go
Normal file
42
pkg/cloudbroker/node/update_description.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package node
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateDescriptionRequest struct to update description of the node
|
||||||
|
type UpdateDescriptionRequest struct {
|
||||||
|
// Node ID
|
||||||
|
// Required: true
|
||||||
|
NID uint64 `url:"nid" json:"nid" validate:"required"`
|
||||||
|
|
||||||
|
// New description for the node
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateDescription updates description of the node
|
||||||
|
func (n Node) UpdateDescription(ctx context.Context, req UpdateDescriptionRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/node/update_description"
|
||||||
|
|
||||||
|
res, err := n.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
|
||||||
|
}
|
||||||
@@ -56,6 +56,9 @@ type ItemStoragePolicy struct {
|
|||||||
// Max IOPS for the sotrage policy
|
// Max IOPS for the sotrage policy
|
||||||
LimitIOPS uint64 `json:"limit_iops"`
|
LimitIOPS uint64 `json:"limit_iops"`
|
||||||
|
|
||||||
|
// Storage policy ID
|
||||||
|
StoragePolicyID uint64 `json:"storage_policy_id"`
|
||||||
|
|
||||||
// Which accounts and resource groups use the storage policy
|
// Which accounts and resource groups use the storage policy
|
||||||
Usage Usage `json:"usage"`
|
Usage Usage `json:"usage"`
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,9 @@ type InfoStoragePolicy struct {
|
|||||||
// Max IOPS for the storage policy
|
// Max IOPS for the storage policy
|
||||||
LimitIOPS uint64 `json:"limit_iops"`
|
LimitIOPS uint64 `json:"limit_iops"`
|
||||||
|
|
||||||
|
// Storage policy ID
|
||||||
|
StoragePolicyID uint64 `json:"storage_policy_id"`
|
||||||
|
|
||||||
// Which accounts and resource groups use the storage policy
|
// Which accounts and resource groups use the storage policy
|
||||||
Usage Usage `json:"usage"`
|
Usage Usage `json:"usage"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -250,6 +250,9 @@ type VNFDev struct {
|
|||||||
|
|
||||||
// Zone ID
|
// Zone ID
|
||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
|
|
||||||
|
// Live migration job ID
|
||||||
|
LiveMigrationJobID uint64 `json:"live_migration_job_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main information about reservation
|
// Main information about reservation
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
// DeleteRequest struct to delete access group
|
// DeleteRequest struct to delete access group
|
||||||
type DeleteRequest struct {
|
type DeleteRequest struct {
|
||||||
// Comment of the access group
|
// ID of the access group
|
||||||
// Required: true
|
// Required: true
|
||||||
GroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
GroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|||||||
46
pkg/sdn/acsgroups/get.go
Normal file
46
pkg/sdn/acsgroups/get.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package acsgroups
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetGroupRequest struct to get an access group
|
||||||
|
type GetGroupRequest struct {
|
||||||
|
// ID of the access group
|
||||||
|
// Required: true
|
||||||
|
GroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info about access group
|
||||||
|
func (i AccessGroups) Get(ctx context.Context, req GetGroupRequest) (*AccessGroup, error) {
|
||||||
|
res, err := i.GetRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
group := AccessGroup{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &group)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &group, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRaw gets a details of group as an array of bytes
|
||||||
|
func (a AccessGroups) GetRaw(ctx context.Context, req GetGroupRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/access_group/get"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -9,8 +9,8 @@ import (
|
|||||||
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PatchRequest struct to update access group
|
// UpdateRequest struct to update access group
|
||||||
type PatchRequest struct {
|
type UpdateRequest struct {
|
||||||
// Access group ID
|
// Access group ID
|
||||||
// Required: true
|
// Required: true
|
||||||
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
@@ -25,13 +25,13 @@ type PatchRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update updates a access groups
|
// Update updates a access groups
|
||||||
func (i AccessGroups) Patch(ctx context.Context, req PatchRequest) (*AccessGroup, error) {
|
func (i AccessGroups) Update(ctx context.Context, req UpdateRequest) (*AccessGroup, error) {
|
||||||
err := validators.ValidateRequest(req)
|
err := validators.ValidateRequest(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "/sdn/access_group/patch"
|
url := "/sdn/access_group/update"
|
||||||
|
|
||||||
res, err := i.client.DecortApiCallCtype(ctx, http.MethodPatch, url, constants.MIMEJSON, req)
|
res, err := i.client.DecortApiCallCtype(ctx, http.MethodPatch, url, constants.MIMEJSON, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
10
pkg/sdn/address_pools.go
Normal file
10
pkg/sdn/address_pools.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package sdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
ap "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/adrspools"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Accessing the SDN method group
|
||||||
|
func (sdn *SDN) AddressPools() *ap.AddressPools {
|
||||||
|
return ap.New(sdn.client)
|
||||||
|
}
|
||||||
18
pkg/sdn/adrspools/adress_pools.go
Normal file
18
pkg/sdn/adrspools/adress_pools.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// API Actor API for managing SDN adress pools
|
||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Structure for creating request to address pools
|
||||||
|
type AddressPools struct {
|
||||||
|
client interfaces.Caller
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder for adress pools endpoints
|
||||||
|
func New(client interfaces.Caller) *AddressPools {
|
||||||
|
return &AddressPools{
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
80
pkg/sdn/adrspools/create.go
Normal file
80
pkg/sdn/adrspools/create.go
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateRequest struct to create address pool
|
||||||
|
type CreateRequest struct {
|
||||||
|
// ID of the access group
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Description of the network
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// Name of the network
|
||||||
|
// Required: true
|
||||||
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
|
// Network address type
|
||||||
|
// Required: true
|
||||||
|
NetAddressType string `url:"net_address_type" json:"net_address_type" validate:"required,addressPoolNetTypeValidator"`
|
||||||
|
|
||||||
|
// List of network addresses
|
||||||
|
// Required: false
|
||||||
|
NetAddresses []NetAddress `url:"net_addresses,omitempty" json:"net_addresses,omitempty" validate:"dive"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetAddress struct representing network address
|
||||||
|
type NetAddress struct {
|
||||||
|
// Network address type
|
||||||
|
// Required: true
|
||||||
|
NetAddressType string `url:"net_address_type" json:"net_address_type" validate:"required,addressPoolNetTypeValidator"`
|
||||||
|
|
||||||
|
// IP address
|
||||||
|
// Required: true
|
||||||
|
IPAddr string `url:"ip_addr" json:"ip_addr" validate:"required"`
|
||||||
|
|
||||||
|
// End of IP address range
|
||||||
|
// Required: false
|
||||||
|
IPAddrRangeEnd string `url:"ip_addr_range_end,omitempty" json:"ip_addr_range_end,omitempty"`
|
||||||
|
|
||||||
|
// IP prefix
|
||||||
|
// Required: false
|
||||||
|
IPPrefix string `url:"ip_prefix,omitempty" json:"ip_prefix,omitempty"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: false
|
||||||
|
MACAddr string `url:"mac_addr,omitempty" json:"mac_addr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates a address pool
|
||||||
|
func (i AddressPools) Create(ctx context.Context, req CreateRequest) (*NetworkAddressPool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/address_pool/create"
|
||||||
|
|
||||||
|
res, err := i.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := NetworkAddressPool{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
51
pkg/sdn/adrspools/delete.go
Normal file
51
pkg/sdn/adrspools/delete.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteRequest struct to delete address pool
|
||||||
|
type DeleteRequest struct {
|
||||||
|
// Address pool ID
|
||||||
|
// Required: true
|
||||||
|
AddressPoolID string `url:"address_pool_id" json:"address_pool_id" validate:"required"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Force delete
|
||||||
|
// Required: false
|
||||||
|
Force interface{} `url:"force,omitempty" json:"force,omitempty" validate:"omitempty,isBool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete an address pool
|
||||||
|
func (i AddressPools) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/address_pool/delete"
|
||||||
|
|
||||||
|
res, err := i.client.DecortApiCallCtype(ctx, http.MethodDelete, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(res) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.ParseBool(string(res))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
42
pkg/sdn/adrspools/filter.go
Normal file
42
pkg/sdn/adrspools/filter.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
// FilterByID returns AddressPoolsList with specified ID.
|
||||||
|
func (agl AddressPoolsList) FilterByID(id string) AddressPoolsList {
|
||||||
|
predicate := func(ia NetworkAddressPool) bool {
|
||||||
|
return ia.ID == id
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByName returns AddressPoolsList with specified Name.
|
||||||
|
func (agl AddressPoolsList) FilterByName(name string) AddressPoolsList {
|
||||||
|
predicate := func(ia NetworkAddressPool) bool {
|
||||||
|
return ia.Name == name
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering AddressPoolsList based on a user-specified predicate.
|
||||||
|
func (agl AddressPoolsList) FilterFunc(predicate func(NetworkAddressPool) bool) AddressPoolsList {
|
||||||
|
var result AddressPoolsList
|
||||||
|
|
||||||
|
for _, acc := range agl.Pools {
|
||||||
|
if predicate(acc) {
|
||||||
|
result.Pools = append(result.Pools, acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first element.
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (agl AddressPoolsList) FindOne() NetworkAddressPool {
|
||||||
|
if len(agl.Pools) == 0 {
|
||||||
|
return NetworkAddressPool{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.Pools[0]
|
||||||
|
}
|
||||||
151
pkg/sdn/adrspools/filter_test.go
Normal file
151
pkg/sdn/adrspools/filter_test.go
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testAddressPools = AddressPoolsList{
|
||||||
|
Pools: []NetworkAddressPool{
|
||||||
|
{
|
||||||
|
ID: "pool1",
|
||||||
|
Name: "DevelopersPool",
|
||||||
|
Description: "First pool",
|
||||||
|
CreatedAt: "2023-01-01",
|
||||||
|
AccessGroupID: "group1",
|
||||||
|
AccessGroupName: "Developers",
|
||||||
|
NetAddressType: "IPv4",
|
||||||
|
NetAddresses: []NetworkAddress{
|
||||||
|
{
|
||||||
|
ID: "addr1",
|
||||||
|
IPAddr: "192.168.1.1",
|
||||||
|
NetAddressType: "IPv4",
|
||||||
|
NetAddressPoolID: "pool1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PoolCounters: PoolCounters{
|
||||||
|
SecurityRules: 5,
|
||||||
|
},
|
||||||
|
VersionID: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "pool2",
|
||||||
|
Name: "AdminsPool",
|
||||||
|
Description: "Second pool",
|
||||||
|
CreatedAt: "2023-01-02",
|
||||||
|
AccessGroupID: "group2",
|
||||||
|
AccessGroupName: "Admins",
|
||||||
|
NetAddressType: "IPv4",
|
||||||
|
NetAddresses: []NetworkAddress{
|
||||||
|
{
|
||||||
|
ID: "addr2",
|
||||||
|
IPAddr: "192.168.1.2",
|
||||||
|
NetAddressType: "IPv4",
|
||||||
|
NetAddressPoolID: "pool2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PoolCounters: PoolCounters{
|
||||||
|
SecurityRules: 3,
|
||||||
|
},
|
||||||
|
VersionID: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "pool3",
|
||||||
|
Name: "UsersPool",
|
||||||
|
Description: "Third pool",
|
||||||
|
CreatedAt: "2023-01-03",
|
||||||
|
AccessGroupID: "group3",
|
||||||
|
AccessGroupName: "Users",
|
||||||
|
NetAddressType: "IPv6",
|
||||||
|
NetAddresses: []NetworkAddress{
|
||||||
|
{
|
||||||
|
ID: "addr3",
|
||||||
|
IPAddr: "2001:db8::1",
|
||||||
|
NetAddressType: "IPv6",
|
||||||
|
NetAddressPoolID: "pool3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PoolCounters: PoolCounters{
|
||||||
|
SecurityRules: 7,
|
||||||
|
},
|
||||||
|
VersionID: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByID(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterByID("pool2").FindOne()
|
||||||
|
|
||||||
|
if actual.ID != "pool2" {
|
||||||
|
t.Fatal("actual:", actual.ID, "> expected: pool2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByName(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterByName("UsersPool").FindOne()
|
||||||
|
|
||||||
|
if actual.Name != "UsersPool" {
|
||||||
|
t.Fatal("actual:", actual.Name, ">> expected: UsersPool")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterFunc(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterFunc(func(ap NetworkAddressPool) bool {
|
||||||
|
return ap.Description == "Second pool"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Pools) != 1 || actual.Pools[0].ID != "pool2" {
|
||||||
|
t.Fatal("Expected 1 pool with description 'Second pool', found:", len(actual.Pools))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneWithResults(t *testing.T) {
|
||||||
|
result := testAddressPools.FilterByID("pool1").FindOne()
|
||||||
|
if result.ID != "pool1" {
|
||||||
|
t.Fatal("Expected pool1, got:", result.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneEmpty(t *testing.T) {
|
||||||
|
emptyList := AddressPoolsList{}
|
||||||
|
result := emptyList.FindOne()
|
||||||
|
|
||||||
|
if result.ID != "" || result.Name != "" {
|
||||||
|
t.Fatal("Expected empty NetworkAddressPool, got:", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIDNotFound(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterByID("nonexistent")
|
||||||
|
|
||||||
|
if len(actual.Pools) != 0 {
|
||||||
|
t.Fatal("Expected 0 pools, found:", len(actual.Pools))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByNameNotFound(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterByName("Nonexistent Pool")
|
||||||
|
|
||||||
|
if len(actual.Pools) != 0 {
|
||||||
|
t.Fatal("Expected 0 pools, found:", len(actual.Pools))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByNetAddressType(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterFunc(func(ap NetworkAddressPool) bool {
|
||||||
|
return ap.NetAddressType == "IPv6"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Pools) != 1 || actual.Pools[0].ID != "pool3" {
|
||||||
|
t.Fatal("Expected 1 pool with IPv6 type, found:", len(actual.Pools))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterBySecurityRulesCount(t *testing.T) {
|
||||||
|
actual := testAddressPools.FilterFunc(func(ap NetworkAddressPool) bool {
|
||||||
|
return ap.PoolCounters.SecurityRules > 4
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Pools) != 2 {
|
||||||
|
t.Fatal("Expected 2 pools with more than 4 security rules, found:", len(actual.Pools))
|
||||||
|
}
|
||||||
|
}
|
||||||
47
pkg/sdn/adrspools/get.go
Normal file
47
pkg/sdn/adrspools/get.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRequest struct to get information about address group
|
||||||
|
type GetRequest struct {
|
||||||
|
// ID an address group
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"address_pool_id" json:"address_pool_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets address pool details as a NetworkAddressPool struct
|
||||||
|
func (a AddressPools) Get(ctx context.Context, req GetRequest) (*NetworkAddressPool, error) {
|
||||||
|
res, err := a.GetRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := NetworkAddressPool{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRaw gets address pool details as an array of bytes
|
||||||
|
func (a AddressPools) GetRaw(ctx context.Context, req GetRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/address_pool/get"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
10
pkg/sdn/adrspools/ids.go
Normal file
10
pkg/sdn/adrspools/ids.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
// IDs gets array of IDs from AddressPoolsList struct
|
||||||
|
func (agl AddressPoolsList) IDs() []string {
|
||||||
|
res := make([]string, 0, len(agl.Pools))
|
||||||
|
for _, c := range agl.Pools {
|
||||||
|
res = append(res, c.ID)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
92
pkg/sdn/adrspools/list.go
Normal file
92
pkg/sdn/adrspools/list.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListAddressPoolsRequest struct to get a list of a groups
|
||||||
|
type ListAddressPoolsRequest struct {
|
||||||
|
// Filter by access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
// Filter by name
|
||||||
|
// Required: false
|
||||||
|
Name string `url:"name,omitempty" json:"name,omitempty"`
|
||||||
|
|
||||||
|
// Filter by minimum address count (greater than or equal to)
|
||||||
|
// Required: false
|
||||||
|
AddrNumberMin uint64 `url:"addr_number_min,omitempty" json:"addr_number_min,omitempty"`
|
||||||
|
|
||||||
|
// Filter by maximum address count (less than)
|
||||||
|
// Required: false
|
||||||
|
AddrNumberMax uint64 `url:"addr_number_max,omitempty" json:"addr_number_max,omitempty"`
|
||||||
|
|
||||||
|
// Updated at lower bound (greater than or equal to)
|
||||||
|
// Required: false
|
||||||
|
UpdatedFrom string `url:"updated_from,omitempty" json:"updated_from,omitempty"`
|
||||||
|
|
||||||
|
// Updated at upper bound (less than)
|
||||||
|
// Required: false
|
||||||
|
UpdatedTo string `url:"updated_to,omitempty" json:"updated_to,omitempty"`
|
||||||
|
|
||||||
|
// Created at lower bound (greater than or equal to)
|
||||||
|
// Required: false
|
||||||
|
CreatedFrom string `url:"created_from,omitempty" json:"created_from,omitempty"`
|
||||||
|
|
||||||
|
// Created at upper bound (less than)
|
||||||
|
// Required: false
|
||||||
|
CreatedTo string `url:"created_to,omitempty" json:"created_to,omitempty"`
|
||||||
|
|
||||||
|
// Page number for pagination
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Number of results per page
|
||||||
|
// Required: false
|
||||||
|
PerPage uint64 `url:"per_page,omitempty" json:"per_page,omitempty"`
|
||||||
|
|
||||||
|
// Field to sort by (name, addr_count, created_at, updated_at)
|
||||||
|
// Required: false
|
||||||
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
||||||
|
|
||||||
|
// Sort order (asc/desc)
|
||||||
|
// Required: false
|
||||||
|
SortOrder string `url:"sort_order,omitempty" json:"sort_order,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of address pools
|
||||||
|
func (i AddressPools) List(ctx context.Context, req ListAddressPoolsRequest) (*AddressPoolsList, error) {
|
||||||
|
res, err := i.ListRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pools := []NetworkAddressPool{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &pools)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := AddressPoolsList{Pools: pools}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRaw gets a list of all address pools as an array of bytes
|
||||||
|
func (a AddressPools) ListRaw(ctx context.Context, req ListAddressPoolsRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/access_group/list"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
62
pkg/sdn/adrspools/models.go
Normal file
62
pkg/sdn/adrspools/models.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
type AddressPoolsList struct {
|
||||||
|
Pools []NetworkAddressPool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main information about network address pool
|
||||||
|
type NetworkAddressPool struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Updated time
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Name
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Network address type
|
||||||
|
NetAddressType string `json:"net_address_type"`
|
||||||
|
|
||||||
|
// List of network addresses
|
||||||
|
NetAddresses []NetworkAddress `json:"net_addresses"`
|
||||||
|
|
||||||
|
// Pool counters
|
||||||
|
PoolCounters PoolCounters `json:"pool_counters"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network address information
|
||||||
|
type NetworkAddress struct {
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// IP address
|
||||||
|
IPAddr string `json:"ip_addr"`
|
||||||
|
|
||||||
|
// Network address type
|
||||||
|
NetAddressType string `json:"net_address_type"`
|
||||||
|
|
||||||
|
// Network address pool ID
|
||||||
|
NetAddressPoolID string `json:"net_address_pool_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool counters information
|
||||||
|
type PoolCounters struct {
|
||||||
|
// Security rules count
|
||||||
|
SecurityRules uint64 `json:"security_rules"`
|
||||||
|
}
|
||||||
43
pkg/sdn/adrspools/serialize.go
Normal file
43
pkg/sdn/adrspools/serialize.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/serialization"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 (la AddressPoolsList) Serialize(params ...string) (serialization.Serialized, error) {
|
||||||
|
if len(la.Pools) == 0 {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params) > 1 {
|
||||||
|
prefix := params[0]
|
||||||
|
indent := params[1]
|
||||||
|
|
||||||
|
return json.MarshalIndent(la, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(la)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (ia NetworkAddressPool) Serialize(params ...string) (serialization.Serialized, error) {
|
||||||
|
if len(params) > 1 {
|
||||||
|
prefix := params[0]
|
||||||
|
indent := params[1]
|
||||||
|
|
||||||
|
return json.MarshalIndent(ia, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(ia)
|
||||||
|
}
|
||||||
84
pkg/sdn/adrspools/update.go
Normal file
84
pkg/sdn/adrspools/update.go
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package adrspools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateRequest struct to update address pool
|
||||||
|
type UpdateRequest struct {
|
||||||
|
// ID of the address pool
|
||||||
|
// Required: true
|
||||||
|
AddressPoolID string `url:"address_pool_id" json:"address_pool_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Description of the network
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// Name of the network
|
||||||
|
// Required: true
|
||||||
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
|
// Network address type
|
||||||
|
// Required: true
|
||||||
|
NetAddressType string `url:"net_address_type" json:"net_address_type" validate:"required,addressPoolNetTypeValidator"`
|
||||||
|
|
||||||
|
// List of network addresses
|
||||||
|
// Required: false
|
||||||
|
NetAddresses []UpdateNetAddress `url:"net_addresses,omitempty" json:"net_addresses,omitempty" validate:"dive"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateNetAddress struct representing network address
|
||||||
|
type UpdateNetAddress struct {
|
||||||
|
// Network address type
|
||||||
|
// Required: true
|
||||||
|
NetAddressType string `url:"net_address_type" json:"net_address_type" validate:"required,addressPoolNetTypeValidator"`
|
||||||
|
|
||||||
|
// IP address
|
||||||
|
// Required: true
|
||||||
|
IPAddr string `url:"ip_addr" json:"ip_addr" validate:"required"`
|
||||||
|
|
||||||
|
// End of IP address range
|
||||||
|
// Required: false
|
||||||
|
IPAddrRangeEnd string `url:"ip_addr_range_end,omitempty" json:"ip_addr_range_end,omitempty"`
|
||||||
|
|
||||||
|
// IP prefix
|
||||||
|
// Required: false
|
||||||
|
IPPrefix string `url:"ip_prefix,omitempty" json:"ip_prefix,omitempty"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: false
|
||||||
|
MACAddr string `url:"mac_addr,omitempty" json:"mac_addr,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates a address pool
|
||||||
|
func (i AddressPools) Update(ctx context.Context, req UpdateRequest) (*NetworkAddressPool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/address_pool/update"
|
||||||
|
|
||||||
|
res, err := i.client.DecortApiCallCtype(ctx, http.MethodPut, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := NetworkAddressPool{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
10
pkg/sdn/default_security_policies.go
Normal file
10
pkg/sdn/default_security_policies.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package sdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
dsp "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/defsecpolicies"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Accessing the SDN method group
|
||||||
|
func (sdn *SDN) DefaultSecurityPolicies() *dsp.DefaultSecurityPolicies {
|
||||||
|
return dsp.New(sdn.client)
|
||||||
|
}
|
||||||
18
pkg/sdn/defsecpolicies/default_security_policies.go
Normal file
18
pkg/sdn/defsecpolicies/default_security_policies.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// API Actor API for managing SDN default secirity policies
|
||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Structure for creating request to default security policies
|
||||||
|
type DefaultSecurityPolicies struct {
|
||||||
|
client interfaces.Caller
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder for adress pools endpoints
|
||||||
|
func New(client interfaces.Caller) *DefaultSecurityPolicies {
|
||||||
|
return &DefaultSecurityPolicies{
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
42
pkg/sdn/defsecpolicies/filter.go
Normal file
42
pkg/sdn/defsecpolicies/filter.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
// FilterByID returns SecurityPoliciesList with specified ID.
|
||||||
|
func (agl SecurityPoliciesList) FilterByID(id string) SecurityPoliciesList {
|
||||||
|
predicate := func(ia SecurityPolicy) bool {
|
||||||
|
return ia.ID == id
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByName returns SecurityPoliciesList with specified Name.
|
||||||
|
func (agl SecurityPoliciesList) FilterByName(name string) SecurityPoliciesList {
|
||||||
|
predicate := func(ia SecurityPolicy) bool {
|
||||||
|
return ia.DisplayName == name
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering SecurityPoliciesList based on a user-specified predicate.
|
||||||
|
func (agl SecurityPoliciesList) FilterFunc(predicate func(SecurityPolicy) bool) SecurityPoliciesList {
|
||||||
|
var result SecurityPoliciesList
|
||||||
|
|
||||||
|
for _, acc := range agl.Policies {
|
||||||
|
if predicate(acc) {
|
||||||
|
result.Policies = append(result.Policies, acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first element.
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (agl SecurityPoliciesList) FindOne() SecurityPolicy {
|
||||||
|
if len(agl.Policies) == 0 {
|
||||||
|
return SecurityPolicy{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.Policies[0]
|
||||||
|
}
|
||||||
268
pkg/sdn/defsecpolicies/filter_test.go
Normal file
268
pkg/sdn/defsecpolicies/filter_test.go
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testSecurityPolicies = SecurityPoliciesList{
|
||||||
|
Policies: []SecurityPolicy{
|
||||||
|
{
|
||||||
|
ID: "policy1",
|
||||||
|
DisplayName: "DevelopersPolicy",
|
||||||
|
Description: "First policy",
|
||||||
|
CreatedAt: "2023-01-01T00:00:00Z",
|
||||||
|
UpdatedAt: "2023-01-01T01:00:00Z",
|
||||||
|
AccessGroupID: "group1",
|
||||||
|
DefaultACLDrop: "DROP",
|
||||||
|
DefaultOpenSessionDrop: true,
|
||||||
|
SecurityRules: []SecurityRule{
|
||||||
|
{
|
||||||
|
ID: "rule1",
|
||||||
|
DisplayName: "DevRule1",
|
||||||
|
Action: "ALLOW",
|
||||||
|
Direction: "INGRESS",
|
||||||
|
Enabled: true,
|
||||||
|
Priority: 100,
|
||||||
|
SecurityPolicyID: "policy1",
|
||||||
|
VersionID: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: Status{
|
||||||
|
Common: "ACTIVE",
|
||||||
|
Hypervisors: []HypervisorStatus{
|
||||||
|
{
|
||||||
|
Name: "hv1",
|
||||||
|
DisplayName: "Hypervisor1",
|
||||||
|
Status: "SYNCED",
|
||||||
|
HypervisorStatus: "HEALTHY",
|
||||||
|
SyncedAt: "2023-01-01T01:00:00Z",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VersionID: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "policy2",
|
||||||
|
DisplayName: "AdminsPolicy",
|
||||||
|
Description: "Second policy",
|
||||||
|
CreatedAt: "2023-01-02T00:00:00Z",
|
||||||
|
UpdatedAt: "2023-01-02T01:00:00Z",
|
||||||
|
AccessGroupID: "group2",
|
||||||
|
DefaultACLDrop: "REJECT",
|
||||||
|
DefaultOpenSessionDrop: false,
|
||||||
|
SecurityRules: []SecurityRule{
|
||||||
|
{
|
||||||
|
ID: "rule2",
|
||||||
|
DisplayName: "AdminRule1",
|
||||||
|
Action: "DENY",
|
||||||
|
Direction: "EGRESS",
|
||||||
|
Enabled: true,
|
||||||
|
Priority: 50,
|
||||||
|
SecurityPolicyID: "policy2",
|
||||||
|
VersionID: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: Status{
|
||||||
|
Common: "ACTIVE",
|
||||||
|
Hypervisors: []HypervisorStatus{
|
||||||
|
{
|
||||||
|
Name: "hv2",
|
||||||
|
DisplayName: "Hypervisor2",
|
||||||
|
Status: "SYNCED",
|
||||||
|
HypervisorStatus: "HEALTHY",
|
||||||
|
SyncedAt: "2023-01-02T01:00:00Z",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VersionID: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "policy3",
|
||||||
|
DisplayName: "UsersPolicy",
|
||||||
|
Description: "Third policy",
|
||||||
|
CreatedAt: "2023-01-03T00:00:00Z",
|
||||||
|
UpdatedAt: "2023-01-03T01:00:00Z",
|
||||||
|
AccessGroupID: "group3",
|
||||||
|
DefaultACLDrop: "DROP",
|
||||||
|
DefaultOpenSessionDrop: true,
|
||||||
|
SecurityRules: []SecurityRule{
|
||||||
|
{
|
||||||
|
ID: "rule3",
|
||||||
|
DisplayName: "UserRule1",
|
||||||
|
Action: "ALLOW",
|
||||||
|
Direction: "INGRESS",
|
||||||
|
Enabled: false,
|
||||||
|
Priority: 200,
|
||||||
|
SecurityPolicyID: "policy3",
|
||||||
|
VersionID: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Status: Status{
|
||||||
|
Common: "PENDING",
|
||||||
|
Hypervisors: []HypervisorStatus{
|
||||||
|
{
|
||||||
|
Name: "hv3",
|
||||||
|
DisplayName: "Hypervisor3",
|
||||||
|
Status: "SYNCING",
|
||||||
|
HypervisorStatus: "HEALTHY",
|
||||||
|
SyncedAt: "2023-01-03T01:00:00Z",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VersionID: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByID(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterByID("policy2").FindOne()
|
||||||
|
|
||||||
|
if actual.ID != "policy2" {
|
||||||
|
t.Fatal("actual:", actual.ID, "> expected: policy2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByDisplayName(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterByName("UsersPolicy").FindOne()
|
||||||
|
|
||||||
|
if actual.DisplayName != "UsersPolicy" {
|
||||||
|
t.Fatal("actual:", actual.DisplayName, ">> expected: UsersPolicy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterFunc(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
return sp.Description == "Second policy"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 1 || actual.Policies[0].ID != "policy2" {
|
||||||
|
t.Fatal("Expected 1 policy with description 'Second policy', found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneWithResults(t *testing.T) {
|
||||||
|
result := testSecurityPolicies.FilterByID("policy1").FindOne()
|
||||||
|
if result.ID != "policy1" {
|
||||||
|
t.Fatal("Expected policy1, got:", result.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneEmpty(t *testing.T) {
|
||||||
|
emptyList := SecurityPoliciesList{}
|
||||||
|
result := emptyList.FindOne()
|
||||||
|
|
||||||
|
if result.ID != "" || result.DisplayName != "" {
|
||||||
|
t.Fatal("Expected empty SecurityPolicy, got:", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIDNotFound(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterByID("nonexistent")
|
||||||
|
|
||||||
|
if len(actual.Policies) != 0 {
|
||||||
|
t.Fatal("Expected 0 policies, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByDisplayNameNotFound(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterByName("Nonexistent Policy")
|
||||||
|
|
||||||
|
if len(actual.Policies) != 0 {
|
||||||
|
t.Fatal("Expected 0 policies, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByDefaultACLDrop(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
return sp.DefaultACLDrop == "DROP"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with DROP default ACL, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByDefaultOpenSessionDrop(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
return sp.DefaultOpenSessionDrop == true
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with default open session drop enabled, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByStatus(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
return sp.Status.Common == "ACTIVE"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with ACTIVE status, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByAccessGroupID(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
return sp.AccessGroupID == "group1"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 1 || actual.Policies[0].ID != "policy1" {
|
||||||
|
t.Fatal("Expected 1 policy with access group ID 'group1', found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByRuleAction(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
for _, rule := range sp.SecurityRules {
|
||||||
|
if rule.Action == "ALLOW" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with ALLOW rules, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByRuleDirection(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
for _, rule := range sp.SecurityRules {
|
||||||
|
if rule.Direction == "INGRESS" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with INGRESS rules, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByRuleEnabled(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
for _, rule := range sp.SecurityRules {
|
||||||
|
if rule.Enabled {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with enabled rules, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByVersionID(t *testing.T) {
|
||||||
|
actual := testSecurityPolicies.FilterFunc(func(sp SecurityPolicy) bool {
|
||||||
|
return sp.VersionID > 1
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Policies) != 2 {
|
||||||
|
t.Fatal("Expected 2 policies with version ID > 1, found:", len(actual.Policies))
|
||||||
|
}
|
||||||
|
}
|
||||||
10
pkg/sdn/defsecpolicies/ids.go
Normal file
10
pkg/sdn/defsecpolicies/ids.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
// IDs gets array of IDs from SecurityPoliciesList struct
|
||||||
|
func (spl SecurityPoliciesList) IDs() []string {
|
||||||
|
res := make([]string, 0, len(spl.Policies))
|
||||||
|
for _, c := range spl.Policies {
|
||||||
|
res = append(res, c.ID)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
64
pkg/sdn/defsecpolicies/list.go
Normal file
64
pkg/sdn/defsecpolicies/list.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListRequest struct to get a list of default security group
|
||||||
|
type ListRequest struct {
|
||||||
|
// Filter by access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
// Page number for pagination
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Number of results per page
|
||||||
|
// Required: false
|
||||||
|
PerPage uint64 `url:"per_page,omitempty" json:"per_page,omitempty"`
|
||||||
|
|
||||||
|
// Field to sort by (name, addr_count, created_at, updated_at)
|
||||||
|
// Required: false
|
||||||
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
||||||
|
|
||||||
|
// Sort order (asc/desc)
|
||||||
|
// Required: false
|
||||||
|
SortOrder string `url:"sort_order,omitempty" json:"sort_order,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of default security policies
|
||||||
|
func (i DefaultSecurityPolicies) List(ctx context.Context, req ListRequest) (*SecurityPoliciesList, error) {
|
||||||
|
res, err := i.ListRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
policies := []SecurityPolicy{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &policies)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := SecurityPoliciesList{Policies: policies}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRaw gets a list of all default security policies as an array of bytes
|
||||||
|
func (a DefaultSecurityPolicies) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/default_security_policy/list"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
191
pkg/sdn/defsecpolicies/models.go
Normal file
191
pkg/sdn/defsecpolicies/models.go
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
type SecurityPoliciesList struct {
|
||||||
|
Policies []SecurityPolicy `json:"policies"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main information about security policy
|
||||||
|
type SecurityPolicy struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Default ACL drop behavior
|
||||||
|
DefaultACLDrop string `json:"default_acl_drop"`
|
||||||
|
|
||||||
|
// Default open session drop flag
|
||||||
|
DefaultOpenSessionDrop bool `json:"default_open_session_drop"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Security rules
|
||||||
|
SecurityRules []SecurityRule `json:"security_rules"`
|
||||||
|
|
||||||
|
// Locked time
|
||||||
|
LockedAt string `json:"locked_at"`
|
||||||
|
|
||||||
|
// Status information
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
|
||||||
|
// Updated time
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security rule information
|
||||||
|
type SecurityRule struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Action
|
||||||
|
Action string `json:"action"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Destination network object
|
||||||
|
DestinationNetObject NetObject `json:"destination_net_object"`
|
||||||
|
|
||||||
|
// Direction
|
||||||
|
Direction string `json:"direction"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Enabled flag
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Filter configuration
|
||||||
|
Filter Filter `json:"filter"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Log enabled flag
|
||||||
|
LogEnabled bool `json:"log_enabled"`
|
||||||
|
|
||||||
|
// Log name
|
||||||
|
LogName string `json:"log_name"`
|
||||||
|
|
||||||
|
// Log severity
|
||||||
|
LogSeverity string `json:"log_severity"`
|
||||||
|
|
||||||
|
// Priority
|
||||||
|
Priority int `json:"priority"`
|
||||||
|
|
||||||
|
// Security policy ID
|
||||||
|
SecurityPolicyID string `json:"security_policy_id"`
|
||||||
|
|
||||||
|
// Source network object
|
||||||
|
SourceNetObject NetObject `json:"source_net_object"`
|
||||||
|
|
||||||
|
// Statistics enabled flag
|
||||||
|
StatisticsEnabled bool `json:"statistics_enabled"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network object information
|
||||||
|
type NetObject struct {
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Network address pool ID
|
||||||
|
NetAddressPoolID string `json:"net_address_pool_id"`
|
||||||
|
|
||||||
|
// Network object group ID
|
||||||
|
NetObjectGroupID string `json:"net_object_group_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter configuration
|
||||||
|
type Filter struct {
|
||||||
|
// Filter parameters
|
||||||
|
Filters FilterParams `json:"filters"`
|
||||||
|
|
||||||
|
// Name
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter parameters
|
||||||
|
type FilterParams struct {
|
||||||
|
// All protocols flag
|
||||||
|
All bool `json:"all"`
|
||||||
|
|
||||||
|
// ARP protocol flag
|
||||||
|
ARP bool `json:"arp"`
|
||||||
|
|
||||||
|
// DHCP protocol flag
|
||||||
|
DHCP bool `json:"dhcp"`
|
||||||
|
|
||||||
|
// Filter expression
|
||||||
|
Expression string `json:"expression"`
|
||||||
|
|
||||||
|
// ICMP protocol flag
|
||||||
|
ICMP bool `json:"icmp"`
|
||||||
|
|
||||||
|
// IP protocol flag
|
||||||
|
IP bool `json:"ip"`
|
||||||
|
|
||||||
|
// IPv4 protocol flag
|
||||||
|
IPv4 bool `json:"ip_v4"`
|
||||||
|
|
||||||
|
// IPv6 protocol flag
|
||||||
|
IPv6 bool `json:"ip_v6"`
|
||||||
|
|
||||||
|
// Keep opened sessions flag
|
||||||
|
KeepOpenedSessions bool `json:"keep_opened_sessions"`
|
||||||
|
|
||||||
|
// ND protocol flag
|
||||||
|
ND bool `json:"nd"`
|
||||||
|
|
||||||
|
// TCP protocol flag
|
||||||
|
TCP bool `json:"tcp"`
|
||||||
|
|
||||||
|
// TCP destination ports
|
||||||
|
TCPDstPorts []string `json:"tcp_dst_ports"`
|
||||||
|
|
||||||
|
// UDP protocol flag
|
||||||
|
UDP bool `json:"udp"`
|
||||||
|
|
||||||
|
// UDP destination ports
|
||||||
|
UDPDstPorts []string `json:"udp_dst_ports"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status information
|
||||||
|
type Status struct {
|
||||||
|
// Common status
|
||||||
|
Common string `json:"common"`
|
||||||
|
|
||||||
|
// Hypervisor statuses
|
||||||
|
Hypervisors []HypervisorStatus `json:"hypervisors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hypervisor status information
|
||||||
|
type HypervisorStatus struct {
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Name
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Hypervisor status
|
||||||
|
HypervisorStatus string `json:"hypervisor_status"`
|
||||||
|
|
||||||
|
// Last sync time
|
||||||
|
SyncedAt string `json:"synced_at"`
|
||||||
|
}
|
||||||
43
pkg/sdn/defsecpolicies/serialize.go
Normal file
43
pkg/sdn/defsecpolicies/serialize.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/serialization"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 (la SecurityPoliciesList) Serialize(params ...string) (serialization.Serialized, error) {
|
||||||
|
if len(la.Policies) == 0 {
|
||||||
|
return []byte{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(params) > 1 {
|
||||||
|
prefix := params[0]
|
||||||
|
indent := params[1]
|
||||||
|
|
||||||
|
return json.MarshalIndent(la, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(la)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 (ia SecurityPolicy) Serialize(params ...string) (serialization.Serialized, error) {
|
||||||
|
if len(params) > 1 {
|
||||||
|
prefix := params[0]
|
||||||
|
indent := params[1]
|
||||||
|
|
||||||
|
return json.MarshalIndent(ia, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(ia)
|
||||||
|
}
|
||||||
53
pkg/sdn/defsecpolicies/update.go
Normal file
53
pkg/sdn/defsecpolicies/update.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package defsecpolicies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateRequest struct to update default security policy
|
||||||
|
type UpdateRequest struct {
|
||||||
|
// ID of the access group
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Default ACL drop behavior
|
||||||
|
// Required: false
|
||||||
|
DefaultACLDrop string `url:"default_acl_drop,omitempty" json:"default_acl_drop,omitempty"`
|
||||||
|
|
||||||
|
// Default open session drop flag
|
||||||
|
// Required: false
|
||||||
|
DefaultOpenSessionDrop bool `url:"default_open_session_drop,omitempty" json:"default_open_session_drop,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates a default security policy
|
||||||
|
func (i DefaultSecurityPolicies) Update(ctx context.Context, req UpdateRequest) (*SecurityPolicy, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/default_security_policy/update"
|
||||||
|
|
||||||
|
res, err := i.client.DecortApiCallCtype(ctx, http.MethodPatch, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := SecurityPolicy{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
10
pkg/sdn/extnet.go
Normal file
10
pkg/sdn/extnet.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package sdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/extnet"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Accessing the ExtNet method group
|
||||||
|
func (sdn *SDN) ExtNet() *extnet.ExtNet {
|
||||||
|
return extnet.New(sdn.client)
|
||||||
|
}
|
||||||
729
pkg/sdn/extnet/create.go
Normal file
729
pkg/sdn/extnet/create.go
Normal file
@@ -0,0 +1,729 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateRequest struct for creating account
|
||||||
|
type CreateRequest struct {
|
||||||
|
// Name of the bridge network
|
||||||
|
// Required: true
|
||||||
|
BridgeNetworkName string `url:"bridge_network_name" json:"bridge_network_name" validate:"required"`
|
||||||
|
|
||||||
|
// Detailed description of the external network
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the network is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// List of hypervisor names
|
||||||
|
// Required: true
|
||||||
|
Hypervisors []string `url:"hypervisors" json:"hypervisors" validate:"required"`
|
||||||
|
|
||||||
|
// List of external network ports
|
||||||
|
// Required: false
|
||||||
|
ExternalNetworkPorts []ExternalNetworkPortRequest `url:"-" json:"external_network_ports,omitempty"`
|
||||||
|
|
||||||
|
// IPv4 default gateway address
|
||||||
|
// Required: false
|
||||||
|
DefaultGatewayIPv4 string `url:"default_gateway_ipv4,omitempty" json:"default_gateway_ipv4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 default gateway address
|
||||||
|
// Required: false
|
||||||
|
DefaultGatewayIPv6 string `url:"default_gateway_ipv6,omitempty" json:"default_gateway_ipv6,omitempty"`
|
||||||
|
|
||||||
|
// IPv4 subnet in CIDR notation (Either subnet_v4 or subnet_v6 must be specified)
|
||||||
|
// Required: false
|
||||||
|
SubnetV4 string `url:"subnet_v4,omitempty" json:"subnet_v4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 subnet in CIDR notation (Either subnet_v4 or subnet_v6 must be specified)
|
||||||
|
// Required: false
|
||||||
|
SubnetV6 string `url:"subnet_v6,omitempty" json:"subnet_v6,omitempty"`
|
||||||
|
|
||||||
|
// VLAN tag identifier
|
||||||
|
// Required: false
|
||||||
|
VLANTag string `url:"vlan_tag,omitempty" json:"vlan_tag,omitempty" validate:"omitempty,trunkTags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExternalNetworkPortRequest struct {
|
||||||
|
// Access group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
// Required: false
|
||||||
|
AccessGroupName string `url:"access_group_name,omitempty" json:"access_group_name,omitempty"`
|
||||||
|
|
||||||
|
// Comment for the external network port
|
||||||
|
// Required: true
|
||||||
|
Comment string `url:"comment" json:"comment" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network port
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the network pork is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// IPv4
|
||||||
|
// Required: false
|
||||||
|
IPv4 string `url:"ipv4,omitempty" json:"ipv4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
// Required: false
|
||||||
|
IPv6 string `url:"ipv6,omitempty" json:"ipv6,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 Config
|
||||||
|
// Required: false
|
||||||
|
IPv6Config *IPv6ConfigRequest `url:"-" json:"ipv6_config,omitempty"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: true
|
||||||
|
MAC string `url:"mac" json:"mac" validate:"required"`
|
||||||
|
|
||||||
|
// Router gateway port
|
||||||
|
// Required: false
|
||||||
|
RouterGatewayPort *RouterGatewayPortRequest `url:"-" json:"router_gateway_port,omitempty"`
|
||||||
|
|
||||||
|
// Floating IP
|
||||||
|
// Required: false
|
||||||
|
FloatingIP *FloatingIPRequest `url:"-" json:"floating_ip,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPv6ConfigRequest struct {
|
||||||
|
//Address Mode (Slaac or DhcpV6Stateful)
|
||||||
|
// Required: true
|
||||||
|
AddressMode string `url:"address_mode" json:"address_mode" validate:"required"`
|
||||||
|
|
||||||
|
// If true, the port will periodically send RA packets.
|
||||||
|
// Required: true
|
||||||
|
EnablePeriodicRa bool `url:"enable_periodic_ra" json:"enable_periodic_ra"`
|
||||||
|
|
||||||
|
// The number of waiting seconds between sending periodic RA
|
||||||
|
// Required: true
|
||||||
|
IntervalRa int64 `url:"interval_ra" json:"interval_ra" validate:"required"`
|
||||||
|
|
||||||
|
// The Default Router Preference (PRF) indicates whether this router should be preferred over other default routers.
|
||||||
|
// high, low, medium
|
||||||
|
// Required: true
|
||||||
|
RouterPreference string `url:"router_preference" json:"router_preference" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterGatewayPortRequest struct {
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// Port id
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"id" json:"id" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network port
|
||||||
|
// Required: true
|
||||||
|
RouterDisplayName string `url:"router_display_name" json:"router_display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Router ID
|
||||||
|
// Required: true
|
||||||
|
RouterID string `url:"router_id" json:"router_id" validate:"required"`
|
||||||
|
|
||||||
|
// SNAT Enabled
|
||||||
|
// Required: true
|
||||||
|
SNATEnabled bool `url:"snat_enabled" json:"snat_enabled"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FloatingIPRequest struct {
|
||||||
|
// Access group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
// Required: true
|
||||||
|
AccessGroupName string `url:"access_group_name" json:"access_group_name" validate:"required"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// External network port
|
||||||
|
// Required: true
|
||||||
|
ExternalNetworkPort string `url:"external_network_port" json:"external_network_port" validate:"required"`
|
||||||
|
|
||||||
|
// ID of the Floating IP
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"id" json:"id" validate:"required"`
|
||||||
|
|
||||||
|
// Logical port
|
||||||
|
// Required: false
|
||||||
|
LogicalPort *LogicalPortRequest `url:"-" json:"logical_port,omitempty"`
|
||||||
|
|
||||||
|
// Router
|
||||||
|
// Required: true
|
||||||
|
Router *RouterRequest `url:"-" json:"router" validate:"required"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogicalPortRequest struct {
|
||||||
|
// Logical Port ID
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"id" json:"id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
// Required: true
|
||||||
|
AccessGroupName string `url:"access_group_name" json:"access_group_name" validate:"required"`
|
||||||
|
|
||||||
|
// MAC of adapter
|
||||||
|
// Required: true
|
||||||
|
AdapterMAC string `url:"adapter_mac" json:"adapter_mac" validate:"required"`
|
||||||
|
|
||||||
|
// Address detection
|
||||||
|
// Required: true
|
||||||
|
AddressDetection bool `url:"address_detection" json:"address_detection" validate:"required"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
// Required: false
|
||||||
|
CreatedAt time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
|
||||||
|
|
||||||
|
// User-friendly name for router
|
||||||
|
// Required: true
|
||||||
|
RouterDisplayName string `url:"router_display_name" json:"router_display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the logical pork is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// External Network ID
|
||||||
|
// Required: false
|
||||||
|
ExternalNetworkID string `url:"external_network_id,omitempty" json:"external_network_id,omitempty"`
|
||||||
|
|
||||||
|
// Hypervisor
|
||||||
|
// Required: true
|
||||||
|
Hypervisor string `url:"hypervisor" json:"hypervisor" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for hypervisor
|
||||||
|
// Required: false
|
||||||
|
HypervisorDisplayName string `url:"hypervisor_display_name,omitempty" json:"hypervisor_display_name,omitempty"`
|
||||||
|
|
||||||
|
// Live Migration Target Hv
|
||||||
|
// Required: true
|
||||||
|
LiveMigrationTargetHV string `url:"live_migration_target_hv" json:"live_migration_target_hv" validate:"required"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
// Required: true
|
||||||
|
Status *StatusRequest `url:"-" json:"status" validate:"required"`
|
||||||
|
|
||||||
|
// Port bindings
|
||||||
|
// Required: true
|
||||||
|
Bindings *PortBindingsRequest `url:"-" json:"bindings" validate:"required"`
|
||||||
|
|
||||||
|
// Unique Identifier
|
||||||
|
// Required: true
|
||||||
|
UniqueIDentifier string `url:"unique_identifier" json:"unique_identifier" validate:"required"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatusRequest struct {
|
||||||
|
// Common
|
||||||
|
// Required: true
|
||||||
|
Common string `url:"common" json:"common" validate:"required"`
|
||||||
|
|
||||||
|
// Hypervisors status
|
||||||
|
// Required: false
|
||||||
|
Hypervisors []HypervisorStatusRequest `url:"-" json:"hypervisors,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PortBindingsRequest struct {
|
||||||
|
// Binding ID
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"id" json:"id" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for segment
|
||||||
|
// Required: true
|
||||||
|
SegmentDisplayName string `url:"segment_display_name" json:"segment_display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Segment ID
|
||||||
|
// Required: true
|
||||||
|
SegmentID string `url:"segment_id" json:"segment_id" validate:"required"`
|
||||||
|
|
||||||
|
// Port security
|
||||||
|
// Required: true
|
||||||
|
PortSecurity bool `url:"port_security" json:"port_security" validate:"required"`
|
||||||
|
|
||||||
|
// Address detection
|
||||||
|
// Required: true
|
||||||
|
AddressDetection bool `url:"address_detection" json:"address_detection" validate:"required"`
|
||||||
|
|
||||||
|
// Is Exclude From Firewall
|
||||||
|
// Required: true
|
||||||
|
IsExcludedFromFirewall bool `url:"is_excluded_from_firewall" json:"is_excluded_from_firewall" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// Logical port addresses
|
||||||
|
// Required: true
|
||||||
|
LogicalPortAddresses []LogicalPortAddressRequest `url:"-" json:"logical_port_addresses" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HypervisorStatusRequest struct {
|
||||||
|
// Status
|
||||||
|
// Required: true
|
||||||
|
Status string `url:"status" json:"status" validate:"required"`
|
||||||
|
|
||||||
|
// Name of hypervisor
|
||||||
|
// Required: true
|
||||||
|
Name string `url:"name" json:"name" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the hypervisor
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Hypervisor status
|
||||||
|
// Required: true
|
||||||
|
HypervisorStatus string `url:"hypervisor_status" json:"hypervisor_status" validate:"required"`
|
||||||
|
|
||||||
|
// Synced at
|
||||||
|
// Required: true
|
||||||
|
SyncedAt time.Time `url:"synced_at" json:"synced_at" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogicalPortAddressRequest struct {
|
||||||
|
// IP of port
|
||||||
|
// Required: true
|
||||||
|
IP string `url:"ip" json:"ip" validate:"required"`
|
||||||
|
|
||||||
|
// IP type (IPv4 or IPv6)
|
||||||
|
// Required: true
|
||||||
|
IPType string `url:"ip_type" json:"ip_type" validate:"required"`
|
||||||
|
|
||||||
|
// Is discovered
|
||||||
|
// Required: false
|
||||||
|
IsDiscovered bool `url:"is_discovered,omitempty" json:"is_discovered,omitempty"`
|
||||||
|
|
||||||
|
// Is discovered
|
||||||
|
// Required: true
|
||||||
|
IsPrimary bool `url:"is_primary" json:"is_primary" validate:"required"`
|
||||||
|
|
||||||
|
// MAC
|
||||||
|
// Required: false
|
||||||
|
MAC string `url:"mac,omitempty" json:"mac,omitempty"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"id" json:"id" validate:"required"`
|
||||||
|
|
||||||
|
// Logical port id
|
||||||
|
// Required: true
|
||||||
|
LogicalPortID string `url:"logical_port_id" json:"logical_port_id" validate:"required"`
|
||||||
|
|
||||||
|
// Assigned at
|
||||||
|
// Required: false
|
||||||
|
AssignedAt time.Time `url:"assigned_at,omitempty" json:"assigned_at,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterRequest struct {
|
||||||
|
// Access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
// Required: false
|
||||||
|
AccessGroupName string `url:"access_group_name,omitempty" json:"access_group_name,omitempty"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
// Required: false
|
||||||
|
CreatedAt time.Time `url:"created_at,omitempty" json:"created_at,omitempty"`
|
||||||
|
|
||||||
|
// Detailed description of the router
|
||||||
|
// Required: false
|
||||||
|
Description string `url:"description,omitempty" json:"description,omitempty"`
|
||||||
|
|
||||||
|
// User-friendly name for the router
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the router is enabled
|
||||||
|
// Required: false
|
||||||
|
Enabled bool `url:"enabled,omitempty" json:"enabled,omitempty"`
|
||||||
|
|
||||||
|
// Gateway ports
|
||||||
|
// Required: false
|
||||||
|
GatewayPorts []GatewayPortRequest `url:"-" json:"gateway_ports,omitempty"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"id" json:"id" validate:"required"`
|
||||||
|
|
||||||
|
// Policies
|
||||||
|
// Required: false
|
||||||
|
Policies []RouterPolicyRequest `url:"-" json:"policies,omitempty"`
|
||||||
|
|
||||||
|
// Ports
|
||||||
|
// Required: false
|
||||||
|
Ports []RouterPortRequest `url:"-" json:"ports,omitempty"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
// Required: false
|
||||||
|
Status *StatusRequest `url:"-" json:"status,omitempty"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: false
|
||||||
|
UpdatedAt time.Time `url:"updated_at,omitempty" json:"updated_at,omitempty"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: false
|
||||||
|
VersionID uint64 `url:"version_id,omitempty" json:"version_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GatewayPortRequest struct {
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// L4 port max
|
||||||
|
// Required: false
|
||||||
|
ExternalL4PortMax int64 `url:"external_l4_port_max,omitempty" json:"external_l4_port_max,omitempty"`
|
||||||
|
|
||||||
|
// L4 port min
|
||||||
|
// Required: false
|
||||||
|
ExternalL4PortMin int64 `url:"external_l4_port_min,omitempty" json:"external_l4_port_min,omitempty"`
|
||||||
|
|
||||||
|
// External network port
|
||||||
|
// Required: true
|
||||||
|
ExternalNetworkPort interface{} `url:"external_network_port" json:"external_network_port" validate:"required"`
|
||||||
|
|
||||||
|
// ID of port
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
|
||||||
|
// SNAT Enabled
|
||||||
|
// Required: true
|
||||||
|
SNATEnabled bool `url:"snat_enabled" json:"snat_enabled"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
// Required: false
|
||||||
|
Status *StatusRequest `url:"-" json:"status,omitempty"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterPolicyRequest struct {
|
||||||
|
// Action
|
||||||
|
// Required: true
|
||||||
|
Action string `url:"action" json:"action" validate:"required"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the policy
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the policy is enabled
|
||||||
|
// Required: false
|
||||||
|
Enabled bool `url:"enabled,omitempty" json:"enabled,omitempty"`
|
||||||
|
|
||||||
|
// ID of port
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Match
|
||||||
|
// Required: true
|
||||||
|
Match interface{} `url:"match" json:"match" validate:"required"`
|
||||||
|
|
||||||
|
// Next IPv4 address
|
||||||
|
// Required: true
|
||||||
|
NextIPv4Address []string `url:"next_ipv4_address" json:"next_ipv4_address" validate:"required"`
|
||||||
|
|
||||||
|
// Next IPv6 address
|
||||||
|
// Required: true
|
||||||
|
NextIPv6Address []string `url:"next_ipv6_address" json:"next_ipv6_address" validate:"required"`
|
||||||
|
|
||||||
|
// Priority
|
||||||
|
// Required: true
|
||||||
|
Priority int64 `url:"priority" json:"priority" validate:"required"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterPortRequest struct {
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// Detailed description of the router port
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the router port is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// ID of port
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Next IPv4 address
|
||||||
|
// Required: true
|
||||||
|
NextIPv4Address []string `url:"next_ipv4_address" json:"next_ipv4_address" validate:"required"`
|
||||||
|
|
||||||
|
// Next IPv6 address
|
||||||
|
// Required: true
|
||||||
|
NextIPv6Address []string `url:"next_ipv6_address" json:"next_ipv6_address" validate:"required"`
|
||||||
|
|
||||||
|
// IPv6 Config
|
||||||
|
// Required: true
|
||||||
|
IPv6Config *IPv6ConfigRequest `url:"-" json:"ipv6_config" validate:"required"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: true
|
||||||
|
MAC string `url:"mac" json:"mac" validate:"required"`
|
||||||
|
|
||||||
|
// Segment
|
||||||
|
// Required: true
|
||||||
|
Segment *SegmentRequest `url:"-" json:"segment" validate:"required"`
|
||||||
|
|
||||||
|
// Segment ID
|
||||||
|
// Required: true
|
||||||
|
SegmentID string `url:"segment_id" json:"segment_id" validate:"required"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
// Required: false
|
||||||
|
Status *StatusRequest `url:"-" json:"status,omitempty"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SegmentRequest struct {
|
||||||
|
// Access group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
// Required: false
|
||||||
|
AccessGroupName string `url:"access_group_name,omitempty" json:"access_group_name,omitempty"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
// Required: true
|
||||||
|
CreatedAt time.Time `url:"created_at" json:"created_at" validate:"required"`
|
||||||
|
|
||||||
|
// Detailed description of the router port
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// DHCP IPv4
|
||||||
|
// Required: false
|
||||||
|
DHCPv4 *DHCPv4ConfigRequest `url:"-" json:"dhcp_v4,omitempty"`
|
||||||
|
|
||||||
|
// DHCP IPv6
|
||||||
|
// Required: false
|
||||||
|
DHCPv6 *DHCPv6ConfigRequest `url:"-" json:"dhcp_v6,omitempty"`
|
||||||
|
|
||||||
|
// User-friendly name for the segment
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the segment is enabled
|
||||||
|
// Required: false
|
||||||
|
Enabled bool `url:"enabled,omitempty" json:"enabled,omitempty"`
|
||||||
|
|
||||||
|
// ID of segment
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Logical ports info
|
||||||
|
// Required: false
|
||||||
|
LogicalPortsInfo []EntityInfoRequest `url:"-" json:"logical_ports_info,omitempty"`
|
||||||
|
|
||||||
|
// Routers info
|
||||||
|
// Required: false
|
||||||
|
RoutersInfo []EntityInfoRequest `url:"-" json:"routers_info,omitempty"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
// Required: false
|
||||||
|
Status *StatusRequest `url:"-" json:"status,omitempty"`
|
||||||
|
|
||||||
|
// IPv4 subnet in CIDR notation (Either subnet_v4 or subnet_v6 must be specified)
|
||||||
|
// Required: false
|
||||||
|
SubnetV4 string `url:"subnet_v4,omitempty" json:"subnet_v4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 subnet in CIDR notation (Either subnet_v4 or subnet_v6 must be specified)
|
||||||
|
// Required: false
|
||||||
|
SubnetV6 string `url:"subnet_v6,omitempty" json:"subnet_v6,omitempty"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
// Required: true
|
||||||
|
UpdatedAt time.Time `url:"updated_at" json:"updated_at" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DHCPv4ConfigRequest struct {
|
||||||
|
// DNS
|
||||||
|
// Required: false
|
||||||
|
DNS []string `url:"dns,omitempty" json:"dns,omitempty"`
|
||||||
|
|
||||||
|
// Excluded address ranges
|
||||||
|
// Required: false
|
||||||
|
ExcludedAddressRanges []string `url:"excluded_address_ranges,omitempty" json:"excluded_address_ranges,omitempty"`
|
||||||
|
|
||||||
|
// Gateway
|
||||||
|
// Required: true
|
||||||
|
Gateway string `url:"gateway" json:"gateway" validate:"required"`
|
||||||
|
|
||||||
|
// ID of config
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Lease time
|
||||||
|
// Required: false
|
||||||
|
LeaseTime int64 `url:"lease_time,omitempty" json:"lease_time,omitempty"`
|
||||||
|
|
||||||
|
// Server IP
|
||||||
|
// Required: true
|
||||||
|
ServerIP string `url:"server_ip" json:"server_ip" validate:"required"`
|
||||||
|
|
||||||
|
// Server MAC
|
||||||
|
// Required: false
|
||||||
|
ServerMAC string `url:"server_mac,omitempty" json:"server_mac,omitempty"`
|
||||||
|
|
||||||
|
// Whether the config is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DHCPv6ConfigRequest struct {
|
||||||
|
// Address prefix
|
||||||
|
// Required: true
|
||||||
|
AddressPrefix string `url:"address_prefix" json:"address_prefix" validate:"required"`
|
||||||
|
|
||||||
|
// DNS
|
||||||
|
// Required: false
|
||||||
|
DNS []string `url:"dns,omitempty" json:"dns,omitempty"`
|
||||||
|
|
||||||
|
// ID of config
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
|
||||||
|
// Lease time
|
||||||
|
// Required: true
|
||||||
|
LeaseTime int64 `url:"lease_time" json:"lease_time" validate:"required"`
|
||||||
|
|
||||||
|
// Server MAC
|
||||||
|
// Required: true
|
||||||
|
ServerMAC string `url:"server_mac" json:"server_mac" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the config is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntityInfoRequest struct {
|
||||||
|
// User-friendly name for the entity
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// ID of entity
|
||||||
|
// Required: false
|
||||||
|
ID string `url:"id,omitempty" json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates extnet
|
||||||
|
func (e ExtNet) Create(ctx context.Context, req CreateRequest) (*ExternalNetworkResponse, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/create"
|
||||||
|
|
||||||
|
res, err := e.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := ExternalNetworkResponse{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
42
pkg/sdn/extnet/delete.go
Normal file
42
pkg/sdn/extnet/delete.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteRequest struct for delete extnet
|
||||||
|
type DeleteRequest struct {
|
||||||
|
// ID of external network
|
||||||
|
// Required: true
|
||||||
|
ExtNetID string `url:"external_network_id" json:"external_network_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Force delete
|
||||||
|
// Required: false
|
||||||
|
Force bool `url:"force,omitempty" json:"force,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete delete an external network
|
||||||
|
func (e ExtNet) Delete(ctx context.Context, req DeleteRequest) error {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/delete"
|
||||||
|
|
||||||
|
_, err = e.client.DecortApiCallCtype(ctx, http.MethodDelete, url, constants.MIMEJSON, req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
18
pkg/sdn/extnet/extnet.go
Normal file
18
pkg/sdn/extnet/extnet.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// API Actor API for managing SDN external networks
|
||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Structure for creating request to external networks
|
||||||
|
type ExtNet struct {
|
||||||
|
client interfaces.Caller
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder for external networks endpoints
|
||||||
|
func New(client interfaces.Caller) *ExtNet {
|
||||||
|
return &ExtNet{
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
60
pkg/sdn/extnet/filter.go
Normal file
60
pkg/sdn/extnet/filter.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
// FilterByID returns ListExtNet with specified ID.
|
||||||
|
func (eList ListExtNet) FilterByID(id string) ListExtNet {
|
||||||
|
predicate := func(extNet ExternalNetworkResponse) bool {
|
||||||
|
return extNet.ID == id
|
||||||
|
}
|
||||||
|
|
||||||
|
return eList.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByName returns ListExtNet with specified Bridge network name.
|
||||||
|
func (eList ListExtNet) FilterByName(name string) ListExtNet {
|
||||||
|
predicate := func(extNet ExternalNetworkResponse) bool {
|
||||||
|
return extNet.BridgeNetworkName == name
|
||||||
|
}
|
||||||
|
|
||||||
|
return eList.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByIPv4 returns ListExtNet with specified default gateway IPv4.
|
||||||
|
func (eList ListExtNet) FilterByIPv4(IPv4 string) ListExtNet {
|
||||||
|
predicate := func(extNet ExternalNetworkResponse) bool {
|
||||||
|
return extNet.DefaultGatewayIPv4 == IPv4
|
||||||
|
}
|
||||||
|
|
||||||
|
return eList.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByIPv6 returns ListExtNet with specified default gateway IPv6.
|
||||||
|
func (eList ListExtNet) FilterByIPv6(IPv6 string) ListExtNet {
|
||||||
|
predicate := func(extNet ExternalNetworkResponse) bool {
|
||||||
|
return extNet.DefaultGatewayIPv6 == IPv6
|
||||||
|
}
|
||||||
|
|
||||||
|
return eList.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering ListExtNet based on a user-specified predicate.
|
||||||
|
func (eList ListExtNet) FilterFunc(predicate func(response ExternalNetworkResponse) bool) ListExtNet {
|
||||||
|
var result ListExtNet
|
||||||
|
|
||||||
|
for _, item := range eList {
|
||||||
|
if predicate(item) {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first element.
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (eList ListExtNet) FindOne() ExternalNetworkResponse {
|
||||||
|
if len(eList) == 0 {
|
||||||
|
return ExternalNetworkResponse{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eList[0]
|
||||||
|
}
|
||||||
149
pkg/sdn/extnet/filter_test.go
Normal file
149
pkg/sdn/extnet/filter_test.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testExtnetList = ListExtNet{
|
||||||
|
{
|
||||||
|
BridgeNetworkName: "br-ext-net-01",
|
||||||
|
DefaultGatewayIPv4: "192.168.1.1",
|
||||||
|
DefaultGatewayIPv6: "2001:db8::1",
|
||||||
|
Description: "test1",
|
||||||
|
Hypervisors: []string{
|
||||||
|
"hv-node-01",
|
||||||
|
},
|
||||||
|
ID: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||||
|
VersionID: 1747141621952,
|
||||||
|
SubnetV4: "192.168.1.0/24",
|
||||||
|
SubnetV6: "2001:db8::/64",
|
||||||
|
CreatedAt: time.Date(2025, 10, 21, 20, 34, 30, 641000000, time.UTC),
|
||||||
|
UpdatedAt: time.Date(2025, 10, 21, 20, 34, 30, 641000000, time.UTC),
|
||||||
|
VLANTag: 100,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BridgeNetworkName: "br-backup-net-02",
|
||||||
|
DefaultGatewayIPv4: "10.0.1.1",
|
||||||
|
DefaultGatewayIPv6: "2001:db8:1::1",
|
||||||
|
Description: "test2",
|
||||||
|
Hypervisors: []string{
|
||||||
|
"hv-node-02",
|
||||||
|
},
|
||||||
|
ID: "b2c3d4e5-f6g7-8901-bcde-f23456789012",
|
||||||
|
VersionID: 1747141621953,
|
||||||
|
SubnetV4: "10.0.1.0/24",
|
||||||
|
SubnetV6: "2001:db8:1::/64",
|
||||||
|
CreatedAt: time.Date(2025, 10, 21, 20, 34, 30, 641000000, time.UTC),
|
||||||
|
UpdatedAt: time.Date(2025, 10, 21, 20, 34, 30, 641000000, time.UTC),
|
||||||
|
VLANTag: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
BridgeNetworkName: "br-test-net-03",
|
||||||
|
DefaultGatewayIPv4: "172.16.1.1",
|
||||||
|
DefaultGatewayIPv6: "2001:db8:2::1",
|
||||||
|
Description: "test3",
|
||||||
|
ExternalNetworkPorts: []ExternalNetworkPort{},
|
||||||
|
Hypervisors: []string{
|
||||||
|
"hv-node-05",
|
||||||
|
"hv-node-06",
|
||||||
|
},
|
||||||
|
ID: "c3d4e5f6-g7h8-9012-cdef-345678901234",
|
||||||
|
VersionID: 1747141621954,
|
||||||
|
SubnetV4: "172.16.1.0/24",
|
||||||
|
SubnetV6: "2001:db8:2::/64",
|
||||||
|
CreatedAt: time.Date(2025, 10, 21, 20, 34, 30, 641000000, time.UTC),
|
||||||
|
UpdatedAt: time.Date(2025, 10, 21, 20, 34, 30, 641000000, time.UTC),
|
||||||
|
VLANTag: 300,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByID(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterByID("a1b2c3d4-e5f6-7890-abcd-ef1234567890").FindOne()
|
||||||
|
|
||||||
|
if actual.ID != "a1b2c3d4-e5f6-7890-abcd-ef1234567890" {
|
||||||
|
t.Fatal("actual:", actual.ID, "> expected: a1b2c3d4-e5f6-7890-abcd-ef1234567890")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByName(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterByName("br-ext-net-01").FindOne()
|
||||||
|
|
||||||
|
if actual.BridgeNetworkName != "br-ext-net-01" {
|
||||||
|
t.Fatal("actual:", actual.BridgeNetworkName, ">> expected: br-ext-net-01")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIPv4(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterByIPv4("192.168.1.1").FindOne()
|
||||||
|
|
||||||
|
if actual.DefaultGatewayIPv4 != "192.168.1.1" {
|
||||||
|
t.Fatal("actual:", actual.DefaultGatewayIPv4, ">> expected: 192.168.1.1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIPv6(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterByIPv6("2001:db8:1::1").FindOne()
|
||||||
|
|
||||||
|
if actual.DefaultGatewayIPv6 != "2001:db8:1::1" {
|
||||||
|
t.Fatal("actual:", actual.DefaultGatewayIPv6, ">> expected: 2001:db8:1::1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterFunc(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterFunc(func(response ExternalNetworkResponse) bool {
|
||||||
|
return response.BridgeNetworkName == "br-backup-net-02"
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual) != 1 || actual[0].ID != "b2c3d4e5-f6g7-8901-bcde-f23456789012" {
|
||||||
|
t.Fatal("Expected 1 extnet with name 'br-backup-net-02', found:", len(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneWithResults(t *testing.T) {
|
||||||
|
result := testExtnetList.FilterByID("c3d4e5f6-g7h8-9012-cdef-345678901234").FindOne()
|
||||||
|
if result.ID != "c3d4e5f6-g7h8-9012-cdef-345678901234" {
|
||||||
|
t.Fatal("Expected c3d4e5f6-g7h8-9012-cdef-345678901234, got:", result.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneEmpty(t *testing.T) {
|
||||||
|
emptyList := ListExtNet{}
|
||||||
|
result := emptyList.FindOne()
|
||||||
|
|
||||||
|
if result.ID != "" || result.BridgeNetworkName != "" {
|
||||||
|
t.Fatal("Expected empty extNet, got:", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIDNotFound(t *testing.T) {
|
||||||
|
actual := ListExtNet{}.FilterByID("nonexistent")
|
||||||
|
|
||||||
|
if len(actual) != 0 {
|
||||||
|
t.Fatal("Expected 0 extNet, found:", len(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByNameNotFound(t *testing.T) {
|
||||||
|
actual := ListExtNet{}.FilterByName("Nonexistent")
|
||||||
|
|
||||||
|
if len(actual) != 0 {
|
||||||
|
t.Fatal("Expected 0 extNet, found:", len(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIPv4NotFound(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterByIPv4("nonexistent-ip")
|
||||||
|
|
||||||
|
if len(actual) != 0 {
|
||||||
|
t.Fatal("Expected 0 extNet, found:", len(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIPv6NotFound(t *testing.T) {
|
||||||
|
actual := testExtnetList.FilterByIPv6("nonexistent-ipv6")
|
||||||
|
|
||||||
|
if len(actual) != 0 {
|
||||||
|
t.Fatal("Expected 0 extNet, found:", len(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
50
pkg/sdn/extnet/get.go
Normal file
50
pkg/sdn/extnet/get.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRequest struct to get information about external network
|
||||||
|
type GetRequest struct {
|
||||||
|
// ID of external network
|
||||||
|
// Required: false
|
||||||
|
ExtNetID string `url:"external_network_id" json:"external_network_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of access group
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets external network details as a ExternalNetworkResponse struct
|
||||||
|
func (e ExtNet) Get(ctx context.Context, req GetRequest) (*ExternalNetworkResponse, error) {
|
||||||
|
res, err := e.GetRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := ExternalNetworkResponse{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRaw gets external network details as an array of bytes
|
||||||
|
func (e ExtNet) GetRaw(ctx context.Context, req GetRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/get"
|
||||||
|
|
||||||
|
res, err := e.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
10
pkg/sdn/extnet/ids.go
Normal file
10
pkg/sdn/extnet/ids.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
// IDs gets array of IDs from ListExtNet struct
|
||||||
|
func (eList ListExtNet) IDs() []string {
|
||||||
|
res := make([]string, 0, len(eList))
|
||||||
|
for _, item := range eList {
|
||||||
|
res = append(res, item.ID)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
114
pkg/sdn/extnet/list.go
Normal file
114
pkg/sdn/extnet/list.go
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListRequest struct to get a list of external networks
|
||||||
|
type ListRequest struct {
|
||||||
|
// Filter by access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
// Filter by display name
|
||||||
|
// Required: false
|
||||||
|
DisplayName string `url:"display_name,omitempty" json:"display_name,omitempty"`
|
||||||
|
|
||||||
|
// Filter by IP version (v4 or v6)
|
||||||
|
// Required: false
|
||||||
|
Subnet string `url:"subnet,omitempty" json:"subnet,omitempty" validate:"omitempty,ipTypes"`
|
||||||
|
|
||||||
|
// Filter by IPv4 subnet (CIDR notation)
|
||||||
|
// Required: false
|
||||||
|
SubnetV4 string `url:"subnet_v4,omitempty" json:"subnet_v4,omitempty"`
|
||||||
|
|
||||||
|
// Filter by IPv4 subnet (CIDR notation)
|
||||||
|
// Required: false
|
||||||
|
SubnetV6 string `url:"subnet_v6,omitempty" json:"subnet_v6,omitempty"`
|
||||||
|
|
||||||
|
// Filter by exact bridge network name
|
||||||
|
// Required: false
|
||||||
|
BridgeNetworkName string `url:"bridge_network_name,omitempty" json:"bridge_network_name,omitempty"`
|
||||||
|
|
||||||
|
// Filter by VLAN tag
|
||||||
|
// Required: false
|
||||||
|
VLANTag string `url:"vlan_tag,omitempty" json:"vlan_tag,omitempty"`
|
||||||
|
|
||||||
|
// Filter by IPv4 default gateway
|
||||||
|
// Required: false
|
||||||
|
DefaultGatewayIPv4 string `url:"default_gateway_ipv4,omitempty" json:"default_gateway_ipv4,omitempty"`
|
||||||
|
|
||||||
|
// Filter by IPv6 default gateway
|
||||||
|
// Required: false
|
||||||
|
DefaultGatewayIPv6 string `url:"default_gateway_ipv6,omitempty" json:"default_gateway_ipv6,omitempty"`
|
||||||
|
|
||||||
|
// Filter by enabled status
|
||||||
|
// Required: false
|
||||||
|
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Filter by update date from
|
||||||
|
// Required: false
|
||||||
|
UpdatedFrom string `url:"updated_from,omitempty" json:"updated_from,omitempty"`
|
||||||
|
|
||||||
|
// Filter lby update date to
|
||||||
|
// Required: false
|
||||||
|
UpdatedTo string `url:"updated_to,omitempty" json:"updated_to,omitempty"`
|
||||||
|
|
||||||
|
// Filter by create date from
|
||||||
|
// Required: false
|
||||||
|
CreatedFrom string `url:"created_from,omitempty" json:"created_from,omitempty"`
|
||||||
|
|
||||||
|
// Filter lby create date to
|
||||||
|
// Required: false
|
||||||
|
CreatedTo string `url:"created_to,omitempty" json:"created_to,omitempty"`
|
||||||
|
|
||||||
|
// Page number for pagination
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Number of results per page
|
||||||
|
// Required: false
|
||||||
|
PerPage uint64 `url:"per_page,omitempty" json:"per_page,omitempty"`
|
||||||
|
|
||||||
|
// Field to sort by (display_name, created_at, updated_at, deleted_at, etc)
|
||||||
|
// Required: false
|
||||||
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
||||||
|
|
||||||
|
// Sort order (asc/desc)
|
||||||
|
// Required: false
|
||||||
|
SortOrder string `url:"sort_order,omitempty" json:"sort_order,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List gets list of all available external networks as a ListExtNet struct
|
||||||
|
func (e ExtNet) List(ctx context.Context, req ListRequest) (ListExtNet, error) {
|
||||||
|
res, err := e.ListRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := ListExtNet{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRaw gets list of all available external networks as an array of bytes
|
||||||
|
func (e ExtNet) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/list"
|
||||||
|
|
||||||
|
res, err := e.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
578
pkg/sdn/extnet/models.go
Normal file
578
pkg/sdn/extnet/models.go
Normal file
@@ -0,0 +1,578 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// List external networks
|
||||||
|
type ListExtNet []ExternalNetworkResponse
|
||||||
|
|
||||||
|
type ExternalNetworkResponse struct {
|
||||||
|
// Name of the bridge network
|
||||||
|
BridgeNetworkName string `json:"bridge_network_name"`
|
||||||
|
|
||||||
|
// IPv4 default gateway address
|
||||||
|
DefaultGatewayIPv4 string `json:"default_gateway_ipv4"`
|
||||||
|
|
||||||
|
// IPv6 default gateway address
|
||||||
|
DefaultGatewayIPv6 string `json:"default_gateway_ipv6"`
|
||||||
|
|
||||||
|
// Detailed description of the external network
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// List of external network ports
|
||||||
|
ExternalNetworkPorts []ExternalNetworkPort `json:"external_network_ports"`
|
||||||
|
|
||||||
|
// List of hypervisor names
|
||||||
|
Hypervisors []string `json:"hypervisors"`
|
||||||
|
|
||||||
|
// Extnet ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
|
||||||
|
// IPv4 subnet in CIDR notation
|
||||||
|
SubnetV4 string `json:"subnet_v4"`
|
||||||
|
|
||||||
|
// IPv6 subnet in CIDR notation
|
||||||
|
SubnetV6 string `json:"subnet_v6"`
|
||||||
|
|
||||||
|
// Creation time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// VLAN tag identifier
|
||||||
|
VLANTag int64 `json:"vlan_tag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExternalNetworkPort struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Comment for the external network port
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network port
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Whether the network port is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// IPv4
|
||||||
|
IPv4 string `json:"ipv4"`
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
IPv6 string `json:"ipv6"`
|
||||||
|
|
||||||
|
// IPv6 Config
|
||||||
|
IPv6Config IPv6Config `json:"ipv6_config"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// Router gateway port
|
||||||
|
RouterGatewayPort RouterGatewayPort `json:"router_gateway_port"`
|
||||||
|
|
||||||
|
// Floating IP
|
||||||
|
FloatingIP FloatingIP `json:"floating_ip"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPv6Config struct {
|
||||||
|
// Address mode
|
||||||
|
AddressMode string `json:"address_mode"`
|
||||||
|
|
||||||
|
// If true, the port will periodically send RA packets.
|
||||||
|
EnablePeriodicRa bool `json:"enable_periodic_ra"`
|
||||||
|
|
||||||
|
// The number of waiting seconds between sending periodic RA
|
||||||
|
IntervalRa int64 `json:"interval_ra"`
|
||||||
|
|
||||||
|
// The Default Router Preference (PRF) indicates whether this router should be preferred over other default routers.
|
||||||
|
RouterPreference string `json:"router_preference"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterGatewayPort struct {
|
||||||
|
// Creation time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Port ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network port
|
||||||
|
RouterDisplayName string `json:"router_display_name"`
|
||||||
|
|
||||||
|
// Router ID
|
||||||
|
RouterID string `json:"router_id"`
|
||||||
|
|
||||||
|
// SNAT Enabled
|
||||||
|
SNATEnabled bool `json:"snat_enabled"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FloatingIP struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// External network port
|
||||||
|
ExternalNetworkPort string `json:"external_network_port"`
|
||||||
|
|
||||||
|
// ID of floating IP
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Logical Port
|
||||||
|
LogicalPort LogicalPort `json:"logical_port"`
|
||||||
|
|
||||||
|
// Router
|
||||||
|
Router Router `json:"router"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogicalPort struct {
|
||||||
|
// Logical Port ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// MAC of adapter
|
||||||
|
AdapterMAC string `json:"adapter_mac"`
|
||||||
|
|
||||||
|
// Address detection
|
||||||
|
AddressDetection bool `json:"address_detection"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// User-friendly name for router
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Whether the logical port is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// External Network ID
|
||||||
|
ExternalNetworkID string `json:"external_network_id"`
|
||||||
|
|
||||||
|
// Hypervisor name
|
||||||
|
Hypervisor string `json:"hypervisor"`
|
||||||
|
|
||||||
|
// User-friendly name for hypervisor
|
||||||
|
HypervisorDisplayName string `json:"hypervisor_display_name"`
|
||||||
|
|
||||||
|
// Live Migration Target Hv
|
||||||
|
LiveMigrationTargetHV string `json:"live_migration_target_hv"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// Bindings struct
|
||||||
|
Bindings PortBindings `json:"bindings"`
|
||||||
|
|
||||||
|
// Unique Identifier
|
||||||
|
UniqueIDentifier string `json:"unique_identifier"`
|
||||||
|
|
||||||
|
// Updated time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PortBindings struct {
|
||||||
|
// Binding ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// User-friendly name for segment
|
||||||
|
SegmentDisplayName string `json:"segment_display_name"`
|
||||||
|
|
||||||
|
// Segment ID
|
||||||
|
SegmentID string `json:"segment_id"`
|
||||||
|
|
||||||
|
// Port security
|
||||||
|
PortSecurity bool `json:"port_security"`
|
||||||
|
|
||||||
|
// Address detection
|
||||||
|
AddressDetection bool `json:"address_detection"`
|
||||||
|
|
||||||
|
// Is Exclude From Firewall
|
||||||
|
IsExcludedFromFirewall bool `json:"is_excluded_from_firewall"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// Logical port addresses
|
||||||
|
LogicalPortAddresses []LogicalPortAddress `json:"logical_port_addresses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogicalPortAddress struct {
|
||||||
|
// IP of port
|
||||||
|
IP string `json:"ip"`
|
||||||
|
|
||||||
|
// IP type (IPv4 or IPv6)
|
||||||
|
IPType string `json:"ip_type"`
|
||||||
|
|
||||||
|
// Is discovered
|
||||||
|
IsDiscovered bool `json:"is_discovered"`
|
||||||
|
|
||||||
|
// Is primary
|
||||||
|
IsPrimary bool `json:"is_primary"`
|
||||||
|
|
||||||
|
// MAC
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Logical port id
|
||||||
|
LogicalPortID string `json:"logical_port_id"`
|
||||||
|
|
||||||
|
// Assigned time
|
||||||
|
AssignedAt time.Time `json:"assigned_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Router struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Detailed description of the router
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// User-friendly name for the router
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Whether the router is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Gateway ports
|
||||||
|
GatewayPorts []GatewayPort `json:"gateway_ports"`
|
||||||
|
|
||||||
|
// ID of router
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Policies
|
||||||
|
Policies []RouterPolicy `json:"policies"`
|
||||||
|
|
||||||
|
// Ports
|
||||||
|
Ports []RouterPort `json:"ports"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GatewayPort struct {
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// L4 port max
|
||||||
|
ExternalL4PortMax int64 `json:"external_l4_port_max"`
|
||||||
|
|
||||||
|
// L4 port min
|
||||||
|
ExternalL4PortMin int64 `json:"external_l4_port_min"`
|
||||||
|
|
||||||
|
// External network port
|
||||||
|
ExternalNetworkPort interface{} `json:"external_network_port"`
|
||||||
|
|
||||||
|
// ID of port
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// SNAT Enabled
|
||||||
|
SNATEnabled bool `json:"snat_enabled"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterPolicy struct {
|
||||||
|
// Action
|
||||||
|
Action string `json:"action"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// User-friendly name for the policy
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Whether the policy is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ID of router policy
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Match
|
||||||
|
Match interface{} `json:"match"`
|
||||||
|
|
||||||
|
// Next IPv4 address
|
||||||
|
NextIPv4Address []string `json:"next_ipv4_address"`
|
||||||
|
|
||||||
|
// Next IPv6 address
|
||||||
|
NextIPv6Address []string `json:"next_ipv6_address"`
|
||||||
|
|
||||||
|
// Priority number
|
||||||
|
Priority int64 `json:"priority"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouterPort struct {
|
||||||
|
// Created at
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Detailed description of the router port
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Whether the router port is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ID of router port
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Next IPv4 address
|
||||||
|
IPv4Address string `json:"ipv4_address"`
|
||||||
|
|
||||||
|
// Next IPv6 address
|
||||||
|
IPv6Address string `json:"ipv6_address"`
|
||||||
|
|
||||||
|
// IPv6 Config
|
||||||
|
IPv6Config IPv6Config `json:"ipv6_config"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// Segment
|
||||||
|
Segment Segment `json:"segment"`
|
||||||
|
|
||||||
|
// Segment ID
|
||||||
|
SegmentID string `json:"segment_id"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Segment struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Created time
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|
||||||
|
// Detailed description of the router port
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// DHCP IPv4
|
||||||
|
DHCPv4 DHCPv4Config `json:"dhcp_v4"`
|
||||||
|
|
||||||
|
// DHCP IPv6
|
||||||
|
DHCPv6 DHCPv6Config `json:"dhcp_v6"`
|
||||||
|
|
||||||
|
// User-friendly name for the segment
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Whether the segment is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ID of segment
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Logical ports info
|
||||||
|
LogicalPortsInfo []EntityInfo `json:"logical_ports_info"`
|
||||||
|
|
||||||
|
// Routers info
|
||||||
|
RoutersInfo []EntityInfo `json:"routers_info"`
|
||||||
|
|
||||||
|
// Status
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// IPv4 subnet in CIDR notation
|
||||||
|
SubnetV4 string `json:"subnet_v4"`
|
||||||
|
|
||||||
|
// IPv6 subnet in CIDR notation
|
||||||
|
SubnetV6 string `json:"subnet_v6"`
|
||||||
|
|
||||||
|
// Update time
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DHCPv4Config struct {
|
||||||
|
// DNS
|
||||||
|
DNS []string `json:"dns"`
|
||||||
|
|
||||||
|
// Excluded address ranges
|
||||||
|
ExcludedAddressRanges []string `json:"excluded_address_ranges"`
|
||||||
|
|
||||||
|
// Gateway
|
||||||
|
Gateway string `json:"gateway"`
|
||||||
|
|
||||||
|
// ID of config
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Lease time
|
||||||
|
LeaseTime int64 `json:"lease_time"`
|
||||||
|
|
||||||
|
// Server IP
|
||||||
|
ServerIP string `json:"server_ip"`
|
||||||
|
|
||||||
|
// Server MAC
|
||||||
|
ServerMAC string `json:"server_mac"`
|
||||||
|
|
||||||
|
// Whether the config is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DHCPv6Config struct {
|
||||||
|
// Address prefix
|
||||||
|
AddressPrefix string `json:"address_prefix"`
|
||||||
|
|
||||||
|
// DNS
|
||||||
|
DNS []string `json:"dns"`
|
||||||
|
|
||||||
|
// ID of config
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Lease time
|
||||||
|
LeaseTime int64 `json:"lease_time"`
|
||||||
|
|
||||||
|
// Server MAC
|
||||||
|
ServerMAC string `json:"server_mac"`
|
||||||
|
|
||||||
|
// Whether the config is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EntityInfo struct {
|
||||||
|
// User-friendly name for the entity
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// ID of entity
|
||||||
|
ID string `json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status struct {
|
||||||
|
// Common
|
||||||
|
Common string `json:"common"`
|
||||||
|
|
||||||
|
// Hypervisors status
|
||||||
|
Hypervisors []HypervisorStatus `json:"hypervisors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HypervisorStatus struct {
|
||||||
|
// Status
|
||||||
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Name of hypervisor
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// User-friendly name for the hypervisor
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Hypervisor status
|
||||||
|
HypervisorStatus string `json:"hypervisor_status"`
|
||||||
|
|
||||||
|
// Synced time
|
||||||
|
SyncedAt time.Time `json:"synced_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExternalNetworkAddPortsResponce struct {
|
||||||
|
// ID of extnet port
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// ID of extnet
|
||||||
|
ExtNetID string `json:"external_network_id"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network port
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Comment
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
|
||||||
|
// Mac
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// IPv4 gateway address
|
||||||
|
IPv4 string `json:"ipv4"`
|
||||||
|
|
||||||
|
// IPv6 gateway address
|
||||||
|
IPv6 string `json:"ipv6"`
|
||||||
|
|
||||||
|
// IPv6 config
|
||||||
|
IPv6Config IPv6Config `json:"ipv6_config"`
|
||||||
|
|
||||||
|
// Whether the network port is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
|
||||||
|
// Router gateway port
|
||||||
|
RouterGatewayPort RouterGatewayPort `json:"router_gateway_port"`
|
||||||
|
}
|
||||||
77
pkg/sdn/extnet/port_add.go
Normal file
77
pkg/sdn/extnet/port_add.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PortAddRequest struct for add port to extnet
|
||||||
|
type PortAddRequest struct {
|
||||||
|
// ID of external network
|
||||||
|
// Required: true
|
||||||
|
ExtNetID string `url:"external_network_id" json:"external_network_id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Description of the port addition operation
|
||||||
|
// Required: true
|
||||||
|
Comment string `url:"comment" json:"comment" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the network is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// IPv4
|
||||||
|
// Required: false
|
||||||
|
IPv4 string `url:"ipv4,omitempty" json:"ipv4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
// Required: false
|
||||||
|
IPv6 string `url:"ipv6,omitempty" json:"ipv6,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 Config
|
||||||
|
// Required: false
|
||||||
|
IPv6Config *IPv6ConfigRequest `url:"-" json:"ipv6_config,omitempty"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: false
|
||||||
|
MAC string `url:"mac,omitempty" json:"mac,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPort added a port an external network
|
||||||
|
func (e ExtNet) AddPort(ctx context.Context, req PortAddRequest) (*ExternalNetworkAddPortsResponce, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/port_add"
|
||||||
|
|
||||||
|
res, err := e.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := ExternalNetworkAddPortsResponce{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
85
pkg/sdn/extnet/port_update.go
Normal file
85
pkg/sdn/extnet/port_update.go
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PortUpdateRequest struct for update port to extnet
|
||||||
|
type PortUpdateRequest struct {
|
||||||
|
// ID of external network
|
||||||
|
// Required: true
|
||||||
|
ExtNetID string `url:"external_network_id" json:"external_network_id" validate:"required"`
|
||||||
|
|
||||||
|
// Access group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Port ID
|
||||||
|
// Required: true
|
||||||
|
PortID string `url:"port_id" json:"port_id" validate:"required"`
|
||||||
|
|
||||||
|
// Port version ID
|
||||||
|
// Required: true
|
||||||
|
PortVersionID uint64 `url:"port_version_id" json:"port_version_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Description of the port addition operation
|
||||||
|
// Required: true
|
||||||
|
Comment string `url:"comment" json:"comment" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Whether the network is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// IPv4
|
||||||
|
// Required: false
|
||||||
|
IPv4 string `url:"ipv4,omitempty" json:"ipv4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
// Required: false
|
||||||
|
IPv6 string `url:"ipv6,omitempty" json:"ipv6,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 Config
|
||||||
|
// Required: false
|
||||||
|
IPv6Config *IPv6ConfigRequest `url:"-" json:"ipv6_config,omitempty"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: false
|
||||||
|
MAC string `url:"mac,omitempty" json:"mac,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePort updated a port an external network
|
||||||
|
func (e ExtNet) UpdatePort(ctx context.Context, req PortUpdateRequest) (*ExternalNetworkResponse, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/port_update"
|
||||||
|
|
||||||
|
res, err := e.client.DecortApiCallCtype(ctx, http.MethodPut, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := ExternalNetworkResponse{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
89
pkg/sdn/extnet/update.go
Normal file
89
pkg/sdn/extnet/update.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package extnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateRequest struct for update extnet
|
||||||
|
type UpdateRequest struct {
|
||||||
|
// ID of external network
|
||||||
|
// Required: true
|
||||||
|
ExtNetID string `url:"external_network_id" json:"external_network_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of version
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Bridge network name
|
||||||
|
// Required: true
|
||||||
|
BridgeNetworkName string `url:"bridge_network_name" json:"bridge_network_name" validate:"required"`
|
||||||
|
|
||||||
|
// Detailed description of the external network
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// User-friendly name for the external network
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// List of hypervisor names
|
||||||
|
// Required: true
|
||||||
|
Hypervisors []string `url:"hypervisors" json:"hypervisors" validate:"required"`
|
||||||
|
|
||||||
|
// Access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
// IPv4 default gateway address
|
||||||
|
// Required: false
|
||||||
|
DefaultGatewayIPv4 string `url:"default_gateway_ipv4,omitempty" json:"default_gateway_ipv4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 default gateway address
|
||||||
|
// Required: false
|
||||||
|
DefaultGatewayIPv6 string `url:"default_gateway_ipv6,omitempty" json:"default_gateway_ipv6,omitempty"`
|
||||||
|
|
||||||
|
// Whether the network is enabled
|
||||||
|
// Required: true
|
||||||
|
Enabled bool `url:"enabled" json:"enabled"`
|
||||||
|
|
||||||
|
// IPv4 subnet in CIDR notation (Either subnet_v4 or subnet_v6 must be specified)
|
||||||
|
// Required: false
|
||||||
|
SubnetV4 string `url:"subnet_v4,omitempty" json:"subnet_v4,omitempty"`
|
||||||
|
|
||||||
|
// IPv6 subnet in CIDR notation (Either subnet_v4 or subnet_v6 must be specified)
|
||||||
|
// Required: false
|
||||||
|
SubnetV6 string `url:"subnet_v6,omitempty" json:"subnet_v6,omitempty"`
|
||||||
|
|
||||||
|
// VLAN tag identifier
|
||||||
|
// Required: false
|
||||||
|
VLANTag string `url:"vlan_tag,omitempty" json:"vlan_tag,omitempty" validate:"omitempty,trunkTags"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updated an external network
|
||||||
|
func (e ExtNet) Update(ctx context.Context, req UpdateRequest) (*ExternalNetworkResponse, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/external_network/update"
|
||||||
|
|
||||||
|
res, err := e.client.DecortApiCallCtype(ctx, http.MethodPut, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := ExternalNetworkResponse{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
10
pkg/sdn/flips.go
Normal file
10
pkg/sdn/flips.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package sdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/flips"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Accessing the SDN method group
|
||||||
|
func (sdn *SDN) FloatingIPs() *flips.FloatingIPs {
|
||||||
|
return flips.New(sdn.client)
|
||||||
|
}
|
||||||
52
pkg/sdn/flips/create.go
Normal file
52
pkg/sdn/flips/create.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateRequest struct {
|
||||||
|
// Access Group ID
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of an external network port
|
||||||
|
// Required: true
|
||||||
|
ExtNetPortID string `url:"external_network_port_id" json:"external_network_port_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of a logical network port
|
||||||
|
// Required: true
|
||||||
|
LogicalPortID string `url:"logical_port_id" json:"logical_port_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of a router
|
||||||
|
// Required: true
|
||||||
|
RouterID string `url:"router_id" json:"router_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates a floating ip
|
||||||
|
func (fi FloatingIPs) Create(ctx context.Context, req CreateRequest) (*RecordFloatingIP, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/floating_ip/create"
|
||||||
|
|
||||||
|
res, err := fi.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := RecordFloatingIP{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
51
pkg/sdn/flips/delete.go
Normal file
51
pkg/sdn/flips/delete.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteRequest to delete a floating ip
|
||||||
|
type DeleteRequest struct {
|
||||||
|
// ID of a floating IP
|
||||||
|
// Required: true
|
||||||
|
FloatingIPID string `url:"floating_ip_id" json:"floating_ip_id" validate:"required"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Force delete
|
||||||
|
// Required: false
|
||||||
|
Force bool `url:"force,omitempty" json:"force,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a floating ip
|
||||||
|
func (fi FloatingIPs) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/floating_ip/delete"
|
||||||
|
|
||||||
|
res, err := fi.client.DecortApiCallCtype(ctx, http.MethodDelete, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if string(res) == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := strconv.ParseBool(string(res))
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
42
pkg/sdn/flips/filter.go
Normal file
42
pkg/sdn/flips/filter.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
// FilterByID returns FloatingIPsList with specified ID.
|
||||||
|
func (fil FloatingIPsList) FilterByID(id string) FloatingIPsList {
|
||||||
|
predicate := func(fi RecordFloatingIP) bool {
|
||||||
|
return fi.ID == id
|
||||||
|
}
|
||||||
|
|
||||||
|
return fil.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByName returns FloatingIPsList with specified AccessGroupName.
|
||||||
|
func (fil FloatingIPsList) FilterByAccessGroupName(name string) FloatingIPsList {
|
||||||
|
predicate := func(fi RecordFloatingIP) bool {
|
||||||
|
return fi.AccessGroupName == name
|
||||||
|
}
|
||||||
|
|
||||||
|
return fil.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering FloatingIPsList based on a user-specified predicate.
|
||||||
|
func (fil FloatingIPsList) FilterFunc(predicate func(fi RecordFloatingIP) bool) FloatingIPsList {
|
||||||
|
var result FloatingIPsList
|
||||||
|
|
||||||
|
for _, acc := range fil.Objects {
|
||||||
|
if predicate(acc) {
|
||||||
|
result.Objects = append(result.Objects, acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first element.
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (fil FloatingIPsList) FindOne() RecordFloatingIP {
|
||||||
|
if len(fil.Objects) == 0 {
|
||||||
|
return RecordFloatingIP{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fil.Objects[0]
|
||||||
|
}
|
||||||
196
pkg/sdn/flips/filter_test.go
Normal file
196
pkg/sdn/flips/filter_test.go
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var testFloatingIPs = FloatingIPsList{
|
||||||
|
Objects: []RecordFloatingIP{
|
||||||
|
{
|
||||||
|
AccessGroupID: "testid",
|
||||||
|
AccessGroupName: "testname",
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
ExternalNetworkPort: ExternalNetworkPort{
|
||||||
|
AccessGroupID: "somegroup",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
Comment: "some comment",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
ExternalNetworkID: "someid",
|
||||||
|
ID: "someid",
|
||||||
|
IPv4: "someipv4",
|
||||||
|
MAC: "somemac",
|
||||||
|
VersionID: 1111111111111,
|
||||||
|
},
|
||||||
|
ID: "someid",
|
||||||
|
LogicalPort: LogicalPort{
|
||||||
|
ID: "someid",
|
||||||
|
AccessGroupID: "someid",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
AdapterMAC: "somemac",
|
||||||
|
AddressDetection: false,
|
||||||
|
Description: "some description",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
Hypervisor: "hypervisor",
|
||||||
|
HypervisorDisplayName: "hypervisor display name",
|
||||||
|
UniqueIdentifier: "someid",
|
||||||
|
VersionID: 1111111111111,
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
},
|
||||||
|
Router: Router{
|
||||||
|
ID: "someid",
|
||||||
|
AccessGroupID: "someid",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
VersionID: 1111111111111,
|
||||||
|
},
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
VersionID: 1111111111111,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
AccessGroupID: "testid3",
|
||||||
|
AccessGroupName: "testname3",
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
ExternalNetworkPort: ExternalNetworkPort{
|
||||||
|
AccessGroupID: "somegroup",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
Comment: "some comment",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
ExternalNetworkID: "someid2",
|
||||||
|
ID: "someid",
|
||||||
|
IPv4: "someipv4",
|
||||||
|
MAC: "somemac",
|
||||||
|
VersionID: 1111111111112,
|
||||||
|
},
|
||||||
|
ID: "someid2",
|
||||||
|
LogicalPort: LogicalPort{
|
||||||
|
ID: "someid2",
|
||||||
|
AccessGroupID: "someid",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
AdapterMAC: "somemac",
|
||||||
|
AddressDetection: false,
|
||||||
|
Description: "some description",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
Hypervisor: "hypervisor",
|
||||||
|
HypervisorDisplayName: "hypervisor display name",
|
||||||
|
UniqueIdentifier: "someid",
|
||||||
|
VersionID: 1111111111112,
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
},
|
||||||
|
Router: Router{
|
||||||
|
ID: "someid2",
|
||||||
|
AccessGroupID: "someid",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
VersionID: 1111111111112,
|
||||||
|
},
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
VersionID: 1111111111112,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
AccessGroupID: "testid3",
|
||||||
|
AccessGroupName: "testname3",
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
ExternalNetworkPort: ExternalNetworkPort{
|
||||||
|
AccessGroupID: "somegroup",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
Comment: "some comment",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
ExternalNetworkID: "someid3",
|
||||||
|
ID: "someid3",
|
||||||
|
IPv4: "someipv4",
|
||||||
|
MAC: "somemac",
|
||||||
|
VersionID: 1111111111113,
|
||||||
|
},
|
||||||
|
ID: "someid3",
|
||||||
|
LogicalPort: LogicalPort{
|
||||||
|
ID: "someid3",
|
||||||
|
AccessGroupID: "someid",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
AdapterMAC: "somemac",
|
||||||
|
AddressDetection: false,
|
||||||
|
Description: "some description",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
Hypervisor: "hypervisor",
|
||||||
|
HypervisorDisplayName: "hypervisor display name",
|
||||||
|
UniqueIdentifier: "someid",
|
||||||
|
VersionID: 1111111111113,
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
},
|
||||||
|
Router: Router{
|
||||||
|
ID: "someid3",
|
||||||
|
AccessGroupID: "someid",
|
||||||
|
AccessGroupName: "somename",
|
||||||
|
CreatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
DisplayName: "some display name",
|
||||||
|
Enabled: true,
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
VersionID: 1111111111113,
|
||||||
|
},
|
||||||
|
UpdatedAt: "2025-09-23T08:05:59.271458Z",
|
||||||
|
VersionID: 1111111111113,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByID(t *testing.T) {
|
||||||
|
actual := testFloatingIPs.FilterByID("someid").FindOne()
|
||||||
|
|
||||||
|
if actual.ID != "someid" {
|
||||||
|
t.Fatal("actual:", actual.ID, "> expected: someid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByName(t *testing.T) {
|
||||||
|
actual := testFloatingIPs.FilterByAccessGroupName("testname").FindOne()
|
||||||
|
|
||||||
|
if actual.AccessGroupName != "testname" {
|
||||||
|
t.Fatal("actual:", actual.AccessGroupID, ">> expected: testname")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterFunc(t *testing.T) {
|
||||||
|
actual := testFloatingIPs.FilterFunc(func(rfi RecordFloatingIP) bool {
|
||||||
|
return rfi.VersionID == 1111111111111
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(actual.Objects) != 1 || actual.Objects[0].ID != "someid" {
|
||||||
|
t.Fatal("Expected 1 policy with version ID 1111111111111, found:", len(actual.Objects))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneWithResults(t *testing.T) {
|
||||||
|
result := testFloatingIPs.FilterByID("someid").FindOne()
|
||||||
|
if result.ID != "someid" {
|
||||||
|
t.Fatal("Expected someid, got:", result.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindOneEmpty(t *testing.T) {
|
||||||
|
emptyList := FloatingIPsList{}
|
||||||
|
result := emptyList.FindOne()
|
||||||
|
|
||||||
|
if result.ID != "" || result.AccessGroupID != "" {
|
||||||
|
t.Fatal("Expected empty FloatingIP, got:", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByIDNotFound(t *testing.T) {
|
||||||
|
actual := testFloatingIPs.FilterByID("nonex")
|
||||||
|
|
||||||
|
if len(actual.Objects) != 0 {
|
||||||
|
t.Fatal("Expected 0 policies, found:", len(actual.Objects))
|
||||||
|
}
|
||||||
|
}
|
||||||
18
pkg/sdn/flips/flips.go
Normal file
18
pkg/sdn/flips/flips.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// API Actor API for managing SDN floating IPs
|
||||||
|
package flips
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Structure for creating request to floating IPs
|
||||||
|
type FloatingIPs struct {
|
||||||
|
client interfaces.Caller
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder for floating IPs endpoints
|
||||||
|
func New(client interfaces.Caller) *FloatingIPs {
|
||||||
|
return &FloatingIPs{
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
46
pkg/sdn/flips/get.go
Normal file
46
pkg/sdn/flips/get.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetRequest struct {
|
||||||
|
// ID of a floating IP
|
||||||
|
// Required: true
|
||||||
|
FloatingIPID string `url:"floating_ip_id" json:"floating_ip_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a floating ip details as a RecordFloatingIP struct
|
||||||
|
func (fi FloatingIPs) Get(ctx context.Context, req GetRequest) (*RecordFloatingIP, error) {
|
||||||
|
res, err := fi.GetRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := RecordFloatingIP{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRaw gets a floating ip details as an array of bytes
|
||||||
|
func (fi FloatingIPs) GetRaw(ctx context.Context, req GetRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/floating_ip/get"
|
||||||
|
|
||||||
|
res, err := fi.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
104
pkg/sdn/flips/list.go
Normal file
104
pkg/sdn/flips/list.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// List of floating ips
|
||||||
|
type ListRequest struct {
|
||||||
|
// Filter by access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
//Is the external network enabled
|
||||||
|
// Required: false
|
||||||
|
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Filter by Pv4 of the associated external network port
|
||||||
|
// Required: false
|
||||||
|
ExternalNetworkPortIPv4 string `url:"external_network_port_ipv4,omitempty" json:"external_network_port_ipv4,omitempty"`
|
||||||
|
|
||||||
|
// Filter by IP of the associated logical port binding
|
||||||
|
// Required: false
|
||||||
|
LogicalPortBindingIP string `url:"logical_port_binding_ip,omitempty" json:"logical_port_binding_ip,omitempty"`
|
||||||
|
|
||||||
|
// Display name of the associated logical port
|
||||||
|
// Required: false
|
||||||
|
LogicalPortDisplayName string `url:"logical_port_display_name,omitempty" json:"logical_port_display_name,omitempty"`
|
||||||
|
|
||||||
|
// Filter by display name of the associated external network
|
||||||
|
// Required: false
|
||||||
|
ExternalNetworkDisplayName string `url:"external_network_display_name,omitempty" json:"external_network_display_name,omitempty"`
|
||||||
|
|
||||||
|
// Filter by display name of the associated router
|
||||||
|
// Required: false
|
||||||
|
RouterDisplayName string `url:"router_display_name,omitempty" json:"router_display_name,omitempty"`
|
||||||
|
|
||||||
|
// Updated at lower bound (greater than or equal to)
|
||||||
|
// Required: false
|
||||||
|
UpdatedFrom string `url:"updated_from,omitempty" json:"updated_from,omitempty"`
|
||||||
|
|
||||||
|
// Updated at upper bound (less than)
|
||||||
|
// Required: false
|
||||||
|
UpdatedTo string `url:"updated_to,omitempty" json:"updated_to,omitempty"`
|
||||||
|
|
||||||
|
// Created at lower bound (greater than or equal to)
|
||||||
|
// Required: false
|
||||||
|
CreatedFrom string `url:"created_from,omitempty" json:"created_from,omitempty"`
|
||||||
|
|
||||||
|
// Created at upper bound (less than)
|
||||||
|
// Required: false
|
||||||
|
CreatedTo string `url:"created_to,omitempty" json:"created_to,omitempty"`
|
||||||
|
|
||||||
|
// Page number for pagination
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Number of results per page
|
||||||
|
// Required: false
|
||||||
|
PerPage uint64 `url:"per_page,omitempty" json:"per_page,omitempty"`
|
||||||
|
|
||||||
|
// Field to sort by (enabled, created_at, updated_at, external_network_port_ipv4, logical_port_binding_ip, logical_port_display_name, external_network_display_name, router_display_name)
|
||||||
|
// Required: false
|
||||||
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
||||||
|
|
||||||
|
// Sort order (asc/desc)
|
||||||
|
// Required: false
|
||||||
|
SortOrder string `url:"sort_order,omitempty" json:"sort_order,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of floating ips
|
||||||
|
func (fi FloatingIPs) List(ctx context.Context, req ListRequest) (*FloatingIPsList, error) {
|
||||||
|
res, err := fi.ListRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
objects := []RecordFloatingIP{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &objects)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := FloatingIPsList{Objects: objects}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRaw gets a list of all floating ips as an array of bytes
|
||||||
|
func (fi FloatingIPs) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/floating_ip/list"
|
||||||
|
|
||||||
|
res, err := fi.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
145
pkg/sdn/flips/models.go
Normal file
145
pkg/sdn/flips/models.go
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
// List of floating ips
|
||||||
|
type FloatingIPsList struct {
|
||||||
|
Objects []RecordFloatingIP
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main info about a floating ip
|
||||||
|
type RecordFloatingIP struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Details of an external network port
|
||||||
|
ExternalNetworkPort ExternalNetworkPort `json:"external_network_port"`
|
||||||
|
|
||||||
|
// ID of a floating IP
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Details of a logical port
|
||||||
|
LogicalPort LogicalPort `json:"logical_port"`
|
||||||
|
|
||||||
|
// Details of a router
|
||||||
|
Router Router `json:"router"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info about a router
|
||||||
|
type Router struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Is a security policy enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info about a logical port
|
||||||
|
type LogicalPort struct {
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Adapter MAC
|
||||||
|
AdapterMAC string `json:"adapter_mac"`
|
||||||
|
|
||||||
|
// Is address detected
|
||||||
|
AddressDetection bool `json:"address_detection"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
Description string `json:"description"`
|
||||||
|
|
||||||
|
// Created at
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Is a logical port enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Hypervisor
|
||||||
|
Hypervisor string `json:"hypervisor"`
|
||||||
|
|
||||||
|
// Hypervisor display name
|
||||||
|
HypervisorDisplayName string `json:"hypervisor_display_name"`
|
||||||
|
|
||||||
|
// Unique identifier
|
||||||
|
UniqueIdentifier string `json:"unique_identifier"`
|
||||||
|
|
||||||
|
// Updated at
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Details of external network ports
|
||||||
|
type ExternalNetworkPort struct {
|
||||||
|
// Access group ID
|
||||||
|
AccessGroupID string `json:"access_group_id"`
|
||||||
|
|
||||||
|
// Access group name
|
||||||
|
AccessGroupName string `json:"access_group_name"`
|
||||||
|
|
||||||
|
// Comment
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
|
||||||
|
// Is a security policy enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// External network ID
|
||||||
|
ExternalNetworkID string `json:"external_network_id"`
|
||||||
|
|
||||||
|
// ID
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// IP v4
|
||||||
|
IPv4 string `json:"ipv4"`
|
||||||
|
|
||||||
|
// MAC
|
||||||
|
MAC string `json:"mac"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
VersionID uint64 `json:"version_id"`
|
||||||
|
}
|
||||||
57
pkg/sdn/flips/update.go
Normal file
57
pkg/sdn/flips/update.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package flips
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UpdateRequest struct to update a floating ip
|
||||||
|
type UpdateRequest struct {
|
||||||
|
// ID of a floating IP
|
||||||
|
// Required: true
|
||||||
|
FloatingIPID string `url:"floating_ip_id" json:"floating_ip_id" validate:"required"`
|
||||||
|
|
||||||
|
// Version ID
|
||||||
|
// Required: true
|
||||||
|
VersionID uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of an external network port
|
||||||
|
// Required: true
|
||||||
|
ExtNetPortID string `url:"external_network_port_id" json:"external_network_port_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of a logical network port
|
||||||
|
// Required: true
|
||||||
|
LogicalPortID string `url:"logical_port_id" json:"logical_port_id" validate:"required"`
|
||||||
|
|
||||||
|
// ID of a router
|
||||||
|
// Required: true
|
||||||
|
RouterID string `url:"router_id" json:"router_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update updates a floating ip
|
||||||
|
func (fi FloatingIPs) Update(ctx context.Context, req UpdateRequest) (*RecordFloatingIP, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/floating_ip/update"
|
||||||
|
|
||||||
|
res, err := fi.client.DecortApiCallCtype(ctx, http.MethodPut, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := RecordFloatingIP{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
10
pkg/sdn/logical_ports.go
Normal file
10
pkg/sdn/logical_ports.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package sdn
|
||||||
|
|
||||||
|
import (
|
||||||
|
lp "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/sdn/logicalports"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Accessing the SDN method group
|
||||||
|
func (sdn *SDN) LogicalPorts() *lp.LogicalPorts {
|
||||||
|
return lp.New(sdn.client)
|
||||||
|
}
|
||||||
104
pkg/sdn/logicalports/create.go
Normal file
104
pkg/sdn/logicalports/create.go
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CreateRequest struct to create logical port
|
||||||
|
type CreateRequest struct {
|
||||||
|
// ID of the access group
|
||||||
|
// Required: true
|
||||||
|
AccessGroupID string `url:"access_group_id" json:"access_group_id" validate:"required"`
|
||||||
|
|
||||||
|
// Description
|
||||||
|
// Required: true
|
||||||
|
Description string `url:"description" json:"description" validate:"required"`
|
||||||
|
|
||||||
|
// Display name
|
||||||
|
// Required: true
|
||||||
|
DisplayName string `url:"display_name" json:"display_name" validate:"required"`
|
||||||
|
|
||||||
|
// Enabled. True or False
|
||||||
|
// Required: true
|
||||||
|
Enabled interface{} `url:"enabled" json:"enabled" validate:"required,isBool"`
|
||||||
|
|
||||||
|
// Is excluded from firewall. True or False
|
||||||
|
// Required: true
|
||||||
|
IsExcludedFromFirewall interface{} `url:"is_excluded_from_firewall" json:"is_excluded_from_firewall" validate:"required,isBool"`
|
||||||
|
|
||||||
|
// Hypervisor
|
||||||
|
// Required: true
|
||||||
|
Hypervisor string `url:"hypervisor" json:"hypervisor" validate:"required"`
|
||||||
|
|
||||||
|
// Port security. True or False
|
||||||
|
// Required: true
|
||||||
|
PortSecurity interface{} `url:"port_security" json:"port_security" validate:"required,isBool"`
|
||||||
|
|
||||||
|
// Segment ID
|
||||||
|
// Required: true
|
||||||
|
SegmentID string `url:"segment_id" json:"segment_id" validate:"required"`
|
||||||
|
|
||||||
|
// Adapter MAC
|
||||||
|
// Required: false
|
||||||
|
AdapterMAC string `url:"adapter_mac,omitempty" json:"adapter_mac,omitempty"`
|
||||||
|
|
||||||
|
// Unique identifier
|
||||||
|
// Required: false
|
||||||
|
UniqueIdentifier string `url:"unique_identifier,omitempty" json:"unique_identifier,omitempty"`
|
||||||
|
|
||||||
|
// Logical port addresses
|
||||||
|
// Required: false
|
||||||
|
LogicalPortAddresses []LogicalPortAddress `url:"logical_port_addresses,omitempty" json:"logical_port_addresses,omitempty" validate:"dive"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogicalPortAddressRequest struct representing logical port address
|
||||||
|
type LogicalPortAddressRequest struct {
|
||||||
|
// IP address
|
||||||
|
// Required: true
|
||||||
|
IP string `url:"ip" json:"ip" validate:"required"`
|
||||||
|
|
||||||
|
// IP type
|
||||||
|
// Required: true
|
||||||
|
IPType string `url:"ip_type" json:"ip_type" validate:"required,oneof=IPv4 IPv6"`
|
||||||
|
|
||||||
|
// Is primary. True or False
|
||||||
|
// Required: true
|
||||||
|
IsPrimary interface{} `url:"is_primary" json:"is_primary" validate:"required,isBool"`
|
||||||
|
|
||||||
|
// MAC address
|
||||||
|
// Required: false
|
||||||
|
MAC string `url:"mac,omitempty" json:"mac,omitempty"`
|
||||||
|
|
||||||
|
// Is discovered. True or False
|
||||||
|
// Required: false
|
||||||
|
IsDiscovered interface{} `url:"is_discovered,omitempty" json:"is_discovered,omitempty" validate:"omitempty,isBool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create creates a logical port
|
||||||
|
func (l LogicalPorts) Create(ctx context.Context, req CreateRequest) (*LogicalPort, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/logical_port/create"
|
||||||
|
|
||||||
|
res, err := l.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := LogicalPort{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
}
|
||||||
41
pkg/sdn/logicalports/delete.go
Normal file
41
pkg/sdn/logicalports/delete.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeleteRequest struct to delete logical port
|
||||||
|
type DeleteRequest struct {
|
||||||
|
// Port ID
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"logical_port_id" json:"logical_port_id" validate:"required"`
|
||||||
|
|
||||||
|
// Version
|
||||||
|
// Required: true
|
||||||
|
Version uint64 `url:"version_id" json:"version_id" validate:"required"`
|
||||||
|
|
||||||
|
// Force delete. True or false
|
||||||
|
// Required: false
|
||||||
|
Force interface{} `url:"force,omitempty" json:"force,omitempty" validate:"omitempty,isBool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a logical port
|
||||||
|
func (i LogicalPorts) Delete(ctx context.Context, req DeleteRequest) (bool, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return false, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/logical_port/delete"
|
||||||
|
|
||||||
|
_, err = i.client.DecortApiCallCtype(ctx, http.MethodDelete, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
42
pkg/sdn/logicalports/filter.go
Normal file
42
pkg/sdn/logicalports/filter.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
// FilterByID returns LogicalPortsList with specified ID.
|
||||||
|
func (agl LogicalPortsList) FilterByID(id string) LogicalPortsList {
|
||||||
|
predicate := func(ia LogicalPort) bool {
|
||||||
|
return ia.ID == id
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByName returns LogicalPortsList with specified Name.
|
||||||
|
func (agl LogicalPortsList) FilterByName(name string) LogicalPortsList {
|
||||||
|
predicate := func(ia LogicalPort) bool {
|
||||||
|
return ia.DisplayName == name
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering LogicalPortsList based on a user-specified predicate.
|
||||||
|
func (agl LogicalPortsList) FilterFunc(predicate func(LogicalPort) bool) LogicalPortsList {
|
||||||
|
var result LogicalPortsList
|
||||||
|
|
||||||
|
for _, acc := range agl.Ports {
|
||||||
|
if predicate(acc) {
|
||||||
|
result.Ports = append(result.Ports, acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first element.
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (agl LogicalPortsList) FindOne() LogicalPort {
|
||||||
|
if len(agl.Ports) == 0 {
|
||||||
|
return LogicalPort{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return agl.Ports[0]
|
||||||
|
}
|
||||||
47
pkg/sdn/logicalports/get.go
Normal file
47
pkg/sdn/logicalports/get.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetRequest struct to get information about logical port
|
||||||
|
type GetRequest struct {
|
||||||
|
// ID a logical port
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"logical_port_id" json:"logical_port_id" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets logical port details as a LogicalPort struct
|
||||||
|
func (a LogicalPorts) Get(ctx context.Context, req GetRequest) (*LogicalPort, error) {
|
||||||
|
res, err := a.GetRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := LogicalPort{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRaw gets logical port details as an array of bytes
|
||||||
|
func (a LogicalPorts) GetRaw(ctx context.Context, req GetRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/logical_port/get"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
47
pkg/sdn/logicalports/get_by_unique_identifier.go
Normal file
47
pkg/sdn/logicalports/get_by_unique_identifier.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetByUniqueIdentifierRequest struct to get information about logical port
|
||||||
|
type GetByUniqueIdentifierRequest struct {
|
||||||
|
// ID a logical port
|
||||||
|
// Required: true
|
||||||
|
ID string `url:"unique_identifier" json:"unique_identifier" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUniqueIdentifier gets logical port details as a LogicalPort struct
|
||||||
|
func (a LogicalPorts) GetByUniqueIdentifier(ctx context.Context, req GetByUniqueIdentifierRequest) (*LogicalPort, error) {
|
||||||
|
res, err := a.GetByUniqueIdentifierRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := LogicalPort{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &info)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &info, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetByUniqueIdentifier gets logical port details as an array of bytes
|
||||||
|
func (a LogicalPorts) GetByUniqueIdentifierRaw(ctx context.Context, req GetByUniqueIdentifierRequest) ([]byte, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/logical_port/get_by_unique_identifier"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
10
pkg/sdn/logicalports/ids.go
Normal file
10
pkg/sdn/logicalports/ids.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
// IDs gets array of IDs from LogicalPortList struct
|
||||||
|
func (pl LogicalPortsList) IDs() []string {
|
||||||
|
res := make([]string, 0, len(pl.Ports))
|
||||||
|
for _, c := range pl.Ports {
|
||||||
|
res = append(res, c.ID)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
120
pkg/sdn/logicalports/list.go
Normal file
120
pkg/sdn/logicalports/list.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListRequest struct to get a list of logical ports
|
||||||
|
type ListRequest struct {
|
||||||
|
// Find by access group ID
|
||||||
|
// Required: false
|
||||||
|
AccessGroupID string `url:"access_group_id,omitempty" json:"access_group_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by segment ID
|
||||||
|
// Required: false
|
||||||
|
SegmentID string `url:"segment_id,omitempty" json:"segment_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by segment display name
|
||||||
|
// Required: false
|
||||||
|
SegmentDisplayName string `url:"segment_display_name,omitempty" json:"segment_display_name,omitempty"`
|
||||||
|
|
||||||
|
// Find by external network ID
|
||||||
|
// Required: false
|
||||||
|
ExternalNetworkID string `url:"external_network_id,omitempty" json:"external_network_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by unique identifier
|
||||||
|
// Required: false
|
||||||
|
UniqueIdentifier string `url:"unique_identifier,omitempty" json:"unique_identifier,omitempty"`
|
||||||
|
|
||||||
|
// Find by display name
|
||||||
|
// Required: false
|
||||||
|
DisplayName string `url:"display_name,omitempty" json:"display_name,omitempty"`
|
||||||
|
|
||||||
|
// Find by adapter MAC address
|
||||||
|
// Required: false
|
||||||
|
AdapterMAC string `url:"adapter_mac,omitempty" json:"adapter_mac,omitempty"`
|
||||||
|
|
||||||
|
// Find by hypervisor
|
||||||
|
// Required: false
|
||||||
|
Hypervisor string `url:"hypervisor,omitempty" json:"hypervisor,omitempty"`
|
||||||
|
|
||||||
|
// Find by hypervisor display name
|
||||||
|
// Required: false
|
||||||
|
HypervisorDisplayName string `url:"hypervisor_display_name,omitempty" json:"hypervisor_display_name,omitempty"`
|
||||||
|
|
||||||
|
// Find by live migration target hypervisor
|
||||||
|
// Required: false
|
||||||
|
LiveMigrationTargetHv string `url:"live_migration_target_hv,omitempty" json:"live_migration_target_hv,omitempty"`
|
||||||
|
|
||||||
|
// Find by port security status, true or false
|
||||||
|
// Required: false
|
||||||
|
PortSecurity interface{} `url:"port_security,omitempty" json:"port_security,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Find by address detection status, true or false
|
||||||
|
// Required: false
|
||||||
|
AddressDetection interface{} `url:"address_detection,omitempty" json:"address_detection,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Find by enabled status, true or false
|
||||||
|
// Required: false
|
||||||
|
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Creation date lower bound (inclusive)
|
||||||
|
// Required: false
|
||||||
|
CreatedFrom string `url:"created_from,omitempty" json:"created_from,omitempty"`
|
||||||
|
|
||||||
|
// Creation date upper bound (inclusive)
|
||||||
|
// Required: false
|
||||||
|
CreatedTo string `url:"created_to,omitempty" json:"created_to,omitempty"`
|
||||||
|
|
||||||
|
// Page number for pagination
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Number of results per page
|
||||||
|
// Required: false
|
||||||
|
PerPage uint64 `url:"per_page,omitempty" json:"per_page,omitempty"`
|
||||||
|
|
||||||
|
// Field to sort by (display_name, created_at, updated_at, deleted_at, segment_id, hypervisor, port_security, segment_display_name, primary_address, hypervisor_display_name)
|
||||||
|
// Required: false
|
||||||
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
||||||
|
|
||||||
|
// Sort order (asc/desc)
|
||||||
|
// Required: false
|
||||||
|
SortOrder string `url:"sort_order,omitempty" json:"sort_order,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of logical portts
|
||||||
|
func (i LogicalPorts) List(ctx context.Context, req ListRequest) (*LogicalPortsList, error) {
|
||||||
|
res, err := i.ListRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
groups := []LogicalPort{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &groups)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := LogicalPortsList{Ports: groups}
|
||||||
|
|
||||||
|
return &result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRaw gets a list of all logical portts as an array of bytes
|
||||||
|
func (a LogicalPorts) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/sdn/logical_port/list"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodGet, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
18
pkg/sdn/logicalports/logicalports.go
Normal file
18
pkg/sdn/logicalports/logicalports.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// API Actor API for managing SDN logical ports
|
||||||
|
package logicalports
|
||||||
|
|
||||||
|
import (
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/interfaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Structure for creating request to logical ports
|
||||||
|
type LogicalPorts struct {
|
||||||
|
client interfaces.Caller
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder for logical ports endpoints
|
||||||
|
func New(client interfaces.Caller) *LogicalPorts {
|
||||||
|
return &LogicalPorts{
|
||||||
|
client,
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user