Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| befff7acd9 |
107
CHANGELOG.md
107
CHANGELOG.md
@@ -1,75 +1,58 @@
|
|||||||
## Version 1.12.3
|
## Version 1.12.4
|
||||||
|
|
||||||
|
Методы `Audits` в cloudapi/compute, cloudbroker/compute, cloudapi/account, cloudbroker/account, cloudapi/vins, cloudbroker/vins, cloudapi/rg и cloudbroker/rg стали deprecated и в следующих версиях будут удалены, вместо них необходимо использовать метод `List` в cloudapi/audit и cloudbroker/audit с соответствующими фильтрами
|
||||||
|
|
||||||
### Добавлено
|
### Добавлено
|
||||||
|
|
||||||
#### account
|
#### audit
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-606 | Поле `policies` в структуру ответа `Resource` в cloudapi/account и в cloudbroker/account |
|
| BGOS-621 | Метод `List` в структура запроса `ListRequest` в cloudapi/audit |
|
||||||
|
| BGOS-621 | Опциональные поля `RGID`, `ComputeID`, `AccountID`, `VINSID`, `ServiceID`, `K8SID`, `FLIPGroupID`, `LBID`, `SEPID`, `NodeID`, `ExcludeAuditLines` в структуру запроса `ListRequest` в cloudbroker/audit |
|
||||||
|
|
||||||
#### compute
|
#### compute
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-603 | Поле `OSVersion` в структуры ответа `RecordCompute` и `ItemCompute` в cloudapi/compute и `RecordCompute` и `InfoCompute` в cloudbroker/compute |
|
| BGOS-613 | Поля `UpdatedTime`, `DeletedBy`, `DeviceName`, `CreatedBy` в структуру ответа `ItemComputeDisk` в cloudapi/compute и в структуру ответа `ItemDisk` в cloudbroker/compute |
|
||||||
| BGOS-603 | Опциональное поле `OSVersion` в структуры запроса `RedeployRequest` и `UpdateRequest` в cloudapi/compute и cloudbroker/compute |
|
| BGOS-613 | Поле `LoaderMetaIso` в структуру ответа `RecordCompute` и структура `LoaderMetaIso` в cloudapi/compute и в cloudbroker/compute |
|
||||||
| BGOS-611 | Методы `StartMigrationIN`, `StopMigrationIN`, `MigrateStorageList` и структуры запросов `StartMigrationINRequest`, `StopMigrationINRequest` и `MigrateStorageListRequest` в cloudbroker/compute |
|
| BGOS-616 | Опциональные поля `PCISlot` и `BusNumber` в структуры запросов `DiskAdd` и `DiskAttach` в cloudapi/compute и cloudbroker/compute |
|
||||||
|
| BGOS-619 | Методы `StartMigrationOut` и `StopMigrationOut` и структуры запросов `StartMigrationOutRequest` и `StopMigrationOutRequest` в cloudbroker/compute |
|
||||||
#### disks
|
| BGOS-619 | Структура `OSUser` в структуру запроса `StopMigrationINRequest` в cloudbroker/compute |
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-609 | Опциональное поле `StoragePolicyID` в структуры запроса `ListUnattachedRequest` и `ListRequest` в cloudapi/disk и cloudbroker/disk |
|
|
||||||
|
|
||||||
#### kvmx86
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-603 | Опциональное поле `OSVersion` в структуры запроса `CreateRequest` и `CreateBlankRequest` в cloudapi/compute и cloudbroker/compute |
|
|
||||||
| BGOS-603 | Опциональное поле `OSVersion` в структуру запроса `MassCreateRequest` в cloudbroker/compute |
|
|
||||||
|
|
||||||
#### node
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-608 | Методы `AddSSHIdentity`, `GetSSHIdentity` и структуры запросов `AddSSHIdentityRequest` и `GetSSHIdentityRequest` в cloudbroker/node |
|
|
||||||
|
|
||||||
#### security group
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-601 | Добавлены комментарии к структурам ответов |
|
|
||||||
|
|
||||||
#### storage policy
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-598 | Поле `sep_name` в структуре ответа `AccessSEPPool` в cloudapi/stpolicy и в cloudbroker/stpolicy |
|
|
||||||
| BGOS-600 | Добавлены комментарии к структурам ответов |
|
|
||||||
|
|
||||||
### Исправлено
|
|
||||||
|
|
||||||
#### account
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-607 | Поле `StoragePolicies` в структуре запроса `CreateRequest` стало опциональным в cloudbroker/account |
|
|
||||||
| BGOS-607 | Изменен тип поля `ID` в структуре запроса `StoragePolicy` с int64 на uint64 в cloudbroker/account |
|
|
||||||
|
|
||||||
#### rg
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-607 | Изменен тип поля `ID` в структуре запроса `StoragePolicy` с int64 на uint64 в cloudapi/rg и в cloudbroker/rg |
|
|
||||||
| BGOS-607 | Поле `StoragePolicies` в структуре запроса `CreateRequest` стало опциональным в cloudbroker/account |
|
|
||||||
|
|
||||||
### Удалено
|
|
||||||
|
|
||||||
#### account
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-605 | Поле `CKey` из структуры ответа `RecordAccount` в cloudapi/account и поля `CKey` из структуры ответа `InfoAccount` и `Meta` из структуры ответа `ItemAccount` в cloudbroker/account |
|
|
||||||
|
|
||||||
#### compute
|
|
||||||
| Идентификатор<br>задачи | Описание |
|
|
||||||
| --- | --- |
|
|
||||||
| BGOS-603 | Поля `VirtualImageID`, `VirtualImageName` из структуры ответа `RecordCompute` и `ItemCompute` в cloudapi/compute и `RecordCompute` и `InfoCompute` в cloudbroker/compute |
|
|
||||||
| BGOS-603 | Поля `ImageID` из структуры ответа `ItemCompute` в cloudapi/compute и `InfoCompute` в cloudbroker/compute |
|
|
||||||
| BGOS-612 | Поле `ImageID` из структуры запроса `ListRequest` в cloudbroker/compute |
|
|
||||||
|
|
||||||
#### image
|
#### image
|
||||||
| Идентификатор<br>задачи | Описание |
|
| Идентификатор<br>задачи | Описание |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| BGOS-604 | Метод `UpdateNodes` и структура запроса `UpdateNodesRequest` в cloudbroker/image |
|
| 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
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BGOS-621 | Поле `Tags` в структуре ответа `ItemAudit` в cloudbroker/audit |
|
||||||
|
|
||||||
|
#### disks
|
||||||
|
| Идентификатор<br>задачи | Описание |
|
||||||
|
| --- | --- |
|
||||||
|
| BGOS-618 | Поле `IOPS` из структуры запроса `CreateRequest` в cloudapi/disks и в cloudbroker/disks |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
81
pkg/cloudapi/audit/filter.go
Normal file
81
pkg/cloudapi/audit/filter.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
// FilterByID returns ListAudits with specified ID.
|
||||||
|
func (la ListAudits) FilterByID(guid string) ListAudits {
|
||||||
|
predicate := func(ia ItemAudit) bool {
|
||||||
|
return ia.GUID == guid
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByCall returns ListAudits with specified call.
|
||||||
|
func (la ListAudits) FilterByCall(call string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.Call == call
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByCorrelationID returns ListAudits with specified correlation id.
|
||||||
|
func (la ListAudits) FilterByCorrelationID(correlationID string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.CorrelationID == correlationID
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByRemoteAddr returns ListAudits with specified remote address.
|
||||||
|
func (la ListAudits) FilterByRemoteAddr(remoteAddr string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.RemoteAddr == remoteAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByUser returns ListAudits with specified user name.
|
||||||
|
func (la ListAudits) FilterByUser(user string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.User == user
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByStatusCode return ListAudits with specified status code.
|
||||||
|
func (la ListAudits) FilterByStatusCode(statusCode uint64) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.StatusCode == statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering ListAudits based on a user-specified predicate.
|
||||||
|
func (la ListAudits) FilterFunc(predicate func(ItemAudit) bool) ListAudits {
|
||||||
|
var result ListAudits
|
||||||
|
|
||||||
|
for _, item := range la.Data {
|
||||||
|
if predicate(item) {
|
||||||
|
result.Data = append(result.Data, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.EntryCount = uint64(len(result.Data))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first found ItemAudit
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (la ListAudits) FindOne() ItemAudit {
|
||||||
|
if len(la.Data) == 0 {
|
||||||
|
return ItemAudit{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.Data[0]
|
||||||
|
}
|
||||||
115
pkg/cloudapi/audit/filter_test.go
Normal file
115
pkg/cloudapi/audit/filter_test.go
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var audits = ListAudits{
|
||||||
|
Data: []ItemAudit{
|
||||||
|
{
|
||||||
|
Args: "[]",
|
||||||
|
Call: "/restmachine/cloudapi/audit/linkedJobs",
|
||||||
|
GUID: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
CorrelationID: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
Kwargs: `{\"audit_guid\":\"dd8623a1-a887-48c1-a500-c10210d404cf\"}`,
|
||||||
|
RemoteAddr: "192.168.1.100",
|
||||||
|
ResponseTime: 1,
|
||||||
|
Result: `[]`,
|
||||||
|
StatusCode: 200,
|
||||||
|
Timestamp: 1640995200,
|
||||||
|
TimestampEnd: 1640995201,
|
||||||
|
User: "test@example.com",
|
||||||
|
TTL: "2025-07-31T14:22:57.028000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: "[]",
|
||||||
|
Call: "/restmachine/cloudapi/audit/test",
|
||||||
|
GUID: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
CorrelationID: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
Kwargs: `{\"audit_guid\":\"dd8623a1-a887-48c1-a500-c10210d404cf\"}`,
|
||||||
|
RemoteAddr: "192.168.1.105",
|
||||||
|
ResponseTime: 5,
|
||||||
|
Result: `[]`,
|
||||||
|
StatusCode: 400,
|
||||||
|
Timestamp: 1640995200,
|
||||||
|
TimestampEnd: 1640995201,
|
||||||
|
User: "test2@example.com",
|
||||||
|
TTL: "2025-07-31T14:22:57.028000",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EntryCount: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByID(t *testing.T) {
|
||||||
|
actual := audits.FilterByID("550e8400-e29b-41d4-a716-446655440002").FindOne()
|
||||||
|
|
||||||
|
if actual.GUID != "550e8400-e29b-41d4-a716-446655440002" {
|
||||||
|
t.Fatal("expected GUID 550e8400-e29b-41d4-a716-446655440002, found: ", actual.GUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByID("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByCorrelationID(t *testing.T) {
|
||||||
|
actual := audits.FilterByCorrelationID("550e8400-e29b-41d4-a716-446655440002").FindOne()
|
||||||
|
|
||||||
|
if actual.CorrelationID != "550e8400-e29b-41d4-a716-446655440002" {
|
||||||
|
t.Fatal("expected GUID 550e8400-e29b-41d4-a716-446655440002, found: ", actual.CorrelationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByCorrelationID("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByRemoteAddr(t *testing.T) {
|
||||||
|
actual := audits.FilterByRemoteAddr("192.168.1.100").FindOne()
|
||||||
|
|
||||||
|
if actual.RemoteAddr != "192.168.1.100" {
|
||||||
|
t.Fatal("expected remote address 192.168.1.100, found: ", actual.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByRemoteAddr("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByUser(t *testing.T) {
|
||||||
|
actual := audits.FilterByUser("test@example.com").FindOne()
|
||||||
|
|
||||||
|
if actual.User != "test@example.com" {
|
||||||
|
t.Fatal("expected user test@example.com, found: ", actual.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByUser("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByCall(t *testing.T) {
|
||||||
|
actual := audits.FilterByCall("/restmachine/cloudapi/audit/test").FindOne()
|
||||||
|
|
||||||
|
if actual.Call != "/restmachine/cloudapi/audit/test" {
|
||||||
|
t.Fatal("expected call /restmachine/cloudapi/audit/test, found: ", actual.Call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByStatusCode(t *testing.T) {
|
||||||
|
actual := audits.FilterByStatusCode(200)
|
||||||
|
|
||||||
|
for _, item := range actual.Data {
|
||||||
|
if item.StatusCode != 200 {
|
||||||
|
t.Fatal("expected 200 status code, found: ", item.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
124
pkg/cloudapi/audit/list.go
Normal file
124
pkg/cloudapi/audit/list.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListRequest struct to give list of account audits
|
||||||
|
type ListRequest struct {
|
||||||
|
|
||||||
|
// Find all audits after point in time (unixtime)
|
||||||
|
// Required: false
|
||||||
|
TimestampAt uint64 `url:"timestamp_at,omitempty" json:"timestamp_at,omitempty"`
|
||||||
|
|
||||||
|
// Find all audits before point in time (unixtime)
|
||||||
|
// Required: false
|
||||||
|
TimestampTo uint64 `url:"timestamp_to,omitempty" json:"timestamp_to,omitempty"`
|
||||||
|
|
||||||
|
// Find by user (Mongo RegExp supported)
|
||||||
|
// Required: false
|
||||||
|
User string `url:"user,omitempty" json:"user,omitempty"`
|
||||||
|
|
||||||
|
// Find by api endpoint (Mongo RegExp supported)
|
||||||
|
// Required: false
|
||||||
|
Call string `url:"call,omitempty" json:"call,omitempty"`
|
||||||
|
|
||||||
|
// Find by request id
|
||||||
|
// Required: false
|
||||||
|
RequestID string `url:"request_id,omitempty" json:"request_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by HTTP min status code
|
||||||
|
// Required: false
|
||||||
|
MinStatusCode uint64 `url:"min_status_code,omitempty" json:"min_status_code,omitempty"`
|
||||||
|
|
||||||
|
// Find by HTTP max status code
|
||||||
|
// Required: false
|
||||||
|
MaxStatusCode uint64 `url:"max_status_code,omitempty" json:"max_status_code,omitempty"`
|
||||||
|
|
||||||
|
// Sort by one of supported fields, format +|-(field)
|
||||||
|
// Required: false
|
||||||
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty" validate:"omitempty,sortBy"`
|
||||||
|
|
||||||
|
// Page number
|
||||||
|
// Required: false
|
||||||
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
|
|
||||||
|
// Page size
|
||||||
|
// Required: false
|
||||||
|
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
||||||
|
|
||||||
|
// Find by resource group id
|
||||||
|
// Required: false
|
||||||
|
RGID uint64 `url:"resgroup_id,omitempty" json:"resgroup_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by compute id
|
||||||
|
// Required: false
|
||||||
|
ComputeID uint64 `url:"compute_id,omitempty" json:"compute_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by account id
|
||||||
|
// Required: false
|
||||||
|
AccountID uint64 `url:"account_id,omitempty" json:"account_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by vins id
|
||||||
|
// Required: false
|
||||||
|
VINSID uint64 `url:"vins_id,omitempty" json:"vins_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by service id
|
||||||
|
// Required: false
|
||||||
|
ServiceID uint64 `url:"service_id,omitempty" json:"service_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by k8s id
|
||||||
|
// Required: false
|
||||||
|
K8SID uint64 `url:"k8s_id,omitempty" json:"k8s_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by flipgroup id
|
||||||
|
// Required: false
|
||||||
|
FLIPGroupID uint64 `url:"flipgroup_id,omitempty" json:"flipgroup_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by load balancer id
|
||||||
|
// Required: false
|
||||||
|
LBID uint64 `url:"lb_id,omitempty" json:"lb_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by sep id
|
||||||
|
// Required: false
|
||||||
|
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
|
||||||
|
|
||||||
|
// Exclude audit lines from response
|
||||||
|
// Required: false
|
||||||
|
ExcludeAuditLines bool `url:"exclude_audit_lines,omitempty" json:"exclude_audit_lines,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List gets audit records for the specified account object
|
||||||
|
func (a Audit) List(ctx context.Context, req ListRequest) (*ListAudits, error) {
|
||||||
|
|
||||||
|
res, err := a.ListRaw(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
list := ListAudits{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(res, &list)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListRaw gets list of audit records an array of bytes
|
||||||
|
func (a Audit) ListRaw(ctx context.Context, req ListRequest) ([]byte, error) {
|
||||||
|
|
||||||
|
if err := validators.ValidateRequest(req); err != nil {
|
||||||
|
return nil, validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudapi/audit/list"
|
||||||
|
|
||||||
|
res, err := a.client.DecortApiCall(ctx, http.MethodPost, url, req)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
@@ -42,3 +42,54 @@ type RecordAudit struct {
|
|||||||
// User
|
// User
|
||||||
User string `json:"user"`
|
User string `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main info about audit
|
||||||
|
type ItemAudit struct {
|
||||||
|
// Args
|
||||||
|
Args string `json:"args"`
|
||||||
|
|
||||||
|
// Call
|
||||||
|
Call string `json:"call"`
|
||||||
|
|
||||||
|
// GUID
|
||||||
|
GUID string `json:"guid"`
|
||||||
|
|
||||||
|
// Correlation ID
|
||||||
|
CorrelationID string `json:"correlation_id"`
|
||||||
|
|
||||||
|
// Kwargs
|
||||||
|
Kwargs string `json:"kwargs"`
|
||||||
|
|
||||||
|
// RemoteAddr
|
||||||
|
RemoteAddr string `json:"remote_addr"`
|
||||||
|
|
||||||
|
// Response time
|
||||||
|
ResponseTime float64 `json:"responsetime"`
|
||||||
|
|
||||||
|
// Result
|
||||||
|
Result string `json:"result"`
|
||||||
|
|
||||||
|
// Status code
|
||||||
|
StatusCode uint64 `json:"statuscode"`
|
||||||
|
|
||||||
|
// Timestamp
|
||||||
|
Timestamp float64 `json:"timestamp"`
|
||||||
|
|
||||||
|
// Timestamp End
|
||||||
|
TimestampEnd float64 `json:"timestampEnd"`
|
||||||
|
|
||||||
|
// User
|
||||||
|
User string `json:"user"`
|
||||||
|
|
||||||
|
// TTL
|
||||||
|
TTL string `json:"_ttl"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of audits
|
||||||
|
type ListAudits struct {
|
||||||
|
// Data
|
||||||
|
Data []ItemAudit `json:"data"`
|
||||||
|
|
||||||
|
// EntryCount
|
||||||
|
EntryCount uint64 `json:"entryCount"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ type DiskAddRequest struct {
|
|||||||
// Specify image id for create disk from template
|
// Specify image id for create disk from template
|
||||||
// Required: false
|
// Required: false
|
||||||
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
|
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
|
||||||
|
|
||||||
|
// Desired PCI slot (hex string, e.g. "0x1A")
|
||||||
|
// Required: false
|
||||||
|
PCISlot string `url:"pci_slot,omitempty" json:"pci_slot,omitempty"`
|
||||||
|
|
||||||
|
// Desired bus number (hex string, e.g. "0x03")
|
||||||
|
// Required: false
|
||||||
|
BusNumber string `url:"bus_number,omitempty" json:"bus_number,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskAdd creates new disk and attach to compute
|
// DiskAdd creates new disk and attach to compute
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ type DiskAttachRequest struct {
|
|||||||
// Type of the disk B;D
|
// Type of the disk B;D
|
||||||
// Required: false
|
// Required: false
|
||||||
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty" validate:"omitempty,computeDiskType"`
|
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty" validate:"omitempty,computeDiskType"`
|
||||||
|
|
||||||
|
// Desired PCI slot (hex string, e.g. "0x1A")
|
||||||
|
// Required: false
|
||||||
|
PCISlot string `url:"pci_slot,omitempty" json:"pci_slot,omitempty"`
|
||||||
|
|
||||||
|
// Desired bus number (hex string, e.g. "0x03")
|
||||||
|
// Required: false
|
||||||
|
BusNumber string `url:"bus_number,omitempty" json:"bus_number,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskAttach attach disk to compute
|
// DiskAttach attach disk to compute
|
||||||
|
|||||||
@@ -392,6 +392,9 @@ type RecordCompute struct {
|
|||||||
// List interfaces
|
// List interfaces
|
||||||
Interfaces ListInterfaces `json:"interfaces"`
|
Interfaces ListInterfaces `json:"interfaces"`
|
||||||
|
|
||||||
|
// Loader meta iso information
|
||||||
|
LoaderMetaIso LoaderMetaIso `json:"loaderMetaIso"`
|
||||||
|
|
||||||
// Live migration job ID
|
// Live migration job ID
|
||||||
LiveMigrationJobID uint64 `json:"live_migration_job_id"`
|
LiveMigrationJobID uint64 `json:"live_migration_job_id"`
|
||||||
|
|
||||||
@@ -519,6 +522,13 @@ type RecordCompute struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
type LoaderMetaIso struct {
|
||||||
|
// Name
|
||||||
|
DeviceName string `json:"devicename"`
|
||||||
|
|
||||||
|
// Path
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
type QemuQuest struct {
|
type QemuQuest struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@@ -758,9 +768,18 @@ type ItemComputeDisk struct {
|
|||||||
// Bus number
|
// Bus number
|
||||||
BusNumber uint64 `json:"bus_number"`
|
BusNumber uint64 `json:"bus_number"`
|
||||||
|
|
||||||
|
// Created by
|
||||||
|
CreatedBy string `json:"createdBy"`
|
||||||
|
|
||||||
// Created time
|
// Created time
|
||||||
CreatedTime uint64 `json:"createdTime"`
|
CreatedTime uint64 `json:"createdTime"`
|
||||||
|
|
||||||
|
// Device name
|
||||||
|
DeviceName string `json:"devicename"`
|
||||||
|
|
||||||
|
// Deleted by
|
||||||
|
DeletedBy string `json:"deletedBy"`
|
||||||
|
|
||||||
// Deleted time
|
// Deleted time
|
||||||
DeletedTime uint64 `json:"deletedTime"`
|
DeletedTime uint64 `json:"deletedTime"`
|
||||||
|
|
||||||
@@ -871,6 +890,9 @@ type ItemComputeDisk struct {
|
|||||||
|
|
||||||
// Updated by
|
// Updated by
|
||||||
UpdatedBy string `json:"updatedBy"`
|
UpdatedBy string `json:"updatedBy"`
|
||||||
|
|
||||||
|
// UpdatedTime
|
||||||
|
UpdatedTime uint64 `json:"updatedTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ItemReplication struct {
|
type ItemReplication struct {
|
||||||
|
|||||||
@@ -30,10 +30,6 @@ type CreateRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
||||||
|
|
||||||
// Max IOPS disk can perform defaults to 2000
|
|
||||||
// Required: false
|
|
||||||
IOPS uint64 `url:"iops,omitempty" json:"iops,omitempty"`
|
|
||||||
|
|
||||||
// Storage endpoint provider ID to create disk
|
// Storage endpoint provider ID to create disk
|
||||||
// Required: false
|
// Required: false
|
||||||
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
|
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ type ListRequest struct {
|
|||||||
// Find by enabled True or False
|
// Find by enabled True or False
|
||||||
// Required: false
|
// Required: false
|
||||||
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Find by storage policy id
|
||||||
|
// Required: false
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List gets list of available images as a ListImages struct, optionally filtering by account ID
|
// List gets list of available images as a ListImages struct, optionally filtering by account ID
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ type ItemImage struct {
|
|||||||
// Status
|
// Status
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
|
|
||||||
|
// Storage policy ID
|
||||||
|
StoragePolicyID uint64 `json:"storage_policy_id"`
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ListRequest struct {
|
type ListRequest struct {
|
||||||
// ID of account ID
|
|
||||||
// Required: true
|
|
||||||
AccountID uint64 `url:"account_id" json:"account_id" validate:"required"`
|
|
||||||
|
|
||||||
// Page number
|
// Page number
|
||||||
// Required: false
|
// Required: false
|
||||||
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
Page uint64 `url:"page,omitempty" json:"page,omitempty"`
|
||||||
@@ -45,6 +41,10 @@ type ListRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty"`
|
||||||
|
|
||||||
|
// ID of account ID
|
||||||
|
// Required: false
|
||||||
|
AccountID uint64 `url:"account_id,omitempty" json:"account_id,omitempty"`
|
||||||
|
|
||||||
// Search by resgroup id
|
// Search by resgroup id
|
||||||
// Required: false
|
// Required: false
|
||||||
ResgroupID uint64 `url:"resgroup_id,omitempty" json:"resgroup_id,omitempty"`
|
ResgroupID uint64 `url:"resgroup_id,omitempty" json:"resgroup_id,omitempty"`
|
||||||
|
|||||||
@@ -211,6 +211,9 @@ type RecordVNFDev struct {
|
|||||||
|
|
||||||
// VNC password
|
// VNC password
|
||||||
VNCPassword string `json:"vncPasswd"`
|
VNCPassword string `json:"vncPasswd"`
|
||||||
|
|
||||||
|
// Zone ID
|
||||||
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// VNF config
|
// VNF config
|
||||||
@@ -269,6 +272,9 @@ type ItemVNFInterface struct {
|
|||||||
// Enabled
|
// Enabled
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Enable security groups
|
||||||
|
EnableSecGroups bool `json:"enable_secgroups"`
|
||||||
|
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
FLIPGroupID uint64 `json:"flipgroupId"`
|
FLIPGroupID uint64 `json:"flipgroupId"`
|
||||||
|
|
||||||
@@ -305,6 +311,9 @@ type ItemVNFInterface struct {
|
|||||||
// NodeID
|
// NodeID
|
||||||
NodeID int64 `json:"nodeId"`
|
NodeID int64 `json:"nodeId"`
|
||||||
|
|
||||||
|
// List of security groups
|
||||||
|
SecGroups []uint64 `json:"security_groups"`
|
||||||
|
|
||||||
// SDNInterfaceID
|
// SDNInterfaceID
|
||||||
SDNInterfaceID string `json:"sdn_interface_id"`
|
SDNInterfaceID string `json:"sdn_interface_id"`
|
||||||
|
|
||||||
@@ -418,6 +427,9 @@ type RecordNAT struct {
|
|||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Zone ID
|
||||||
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NAT configuration
|
// NAT configuration
|
||||||
@@ -486,6 +498,9 @@ type RecordGW struct {
|
|||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Zone ID
|
||||||
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GW configuration
|
// GW configuration
|
||||||
@@ -576,6 +591,9 @@ type RecordDHCP struct {
|
|||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Zone ID
|
||||||
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DHCP configuration
|
// DHCP configuration
|
||||||
|
|||||||
81
pkg/cloudbroker/audit/filter.go
Normal file
81
pkg/cloudbroker/audit/filter.go
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
// FilterByID returns ListAudits with specified ID.
|
||||||
|
func (la ListAudits) FilterByID(guid string) ListAudits {
|
||||||
|
predicate := func(ia ItemAudit) bool {
|
||||||
|
return ia.GUID == guid
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByCall returns ListAudits with specified call.
|
||||||
|
func (la ListAudits) FilterByCall(call string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.Call == call
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByCorrelationID returns ListAudits with specified correlation id.
|
||||||
|
func (la ListAudits) FilterByCorrelationID(correlationID string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.CorrelationID == correlationID
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByRemoteAddr returns ListAudits with specified remote address.
|
||||||
|
func (la ListAudits) FilterByRemoteAddr(remoteAddr string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.RemoteAddr == remoteAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByUser returns ListAudits with specified user name.
|
||||||
|
func (la ListAudits) FilterByUser(user string) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.User == user
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterByStatusCode return ListAudits with specified status code.
|
||||||
|
func (la ListAudits) FilterByStatusCode(statusCode uint64) ListAudits {
|
||||||
|
predicate := func(ic ItemAudit) bool {
|
||||||
|
return ic.StatusCode == statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.FilterFunc(predicate)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunc allows filtering ListAudits based on a user-specified predicate.
|
||||||
|
func (la ListAudits) FilterFunc(predicate func(ItemAudit) bool) ListAudits {
|
||||||
|
var result ListAudits
|
||||||
|
|
||||||
|
for _, item := range la.Data {
|
||||||
|
if predicate(item) {
|
||||||
|
result.Data = append(result.Data, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.EntryCount = uint64(len(result.Data))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindOne returns first found ItemAudit
|
||||||
|
// If none was found, returns an empty struct.
|
||||||
|
func (la ListAudits) FindOne() ItemAudit {
|
||||||
|
if len(la.Data) == 0 {
|
||||||
|
return ItemAudit{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return la.Data[0]
|
||||||
|
}
|
||||||
115
pkg/cloudbroker/audit/filter_test.go
Normal file
115
pkg/cloudbroker/audit/filter_test.go
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package audit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var audits = ListAudits{
|
||||||
|
Data: []ItemAudit{
|
||||||
|
{
|
||||||
|
Args: "[]",
|
||||||
|
Call: "/restmachine/cloudapi/audit/linkedJobs",
|
||||||
|
GUID: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
CorrelationID: "550e8400-e29b-41d4-a716-446655440001",
|
||||||
|
Kwargs: `{\"audit_guid\":\"dd8623a1-a887-48c1-a500-c10210d404cf\"}`,
|
||||||
|
RemoteAddr: "192.168.1.100",
|
||||||
|
ResponseTime: 1,
|
||||||
|
Result: `[]`,
|
||||||
|
StatusCode: 200,
|
||||||
|
Timestamp: 1640995200,
|
||||||
|
TimestampEnd: 1640995201,
|
||||||
|
User: "test@example.com",
|
||||||
|
TTL: "2025-07-31T14:22:57.028000",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: "[]",
|
||||||
|
Call: "/restmachine/cloudapi/audit/test",
|
||||||
|
GUID: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
CorrelationID: "550e8400-e29b-41d4-a716-446655440002",
|
||||||
|
Kwargs: `{\"audit_guid\":\"dd8623a1-a887-48c1-a500-c10210d404cf\"}`,
|
||||||
|
RemoteAddr: "192.168.1.105",
|
||||||
|
ResponseTime: 5,
|
||||||
|
Result: `[]`,
|
||||||
|
StatusCode: 400,
|
||||||
|
Timestamp: 1640995200,
|
||||||
|
TimestampEnd: 1640995201,
|
||||||
|
User: "test2@example.com",
|
||||||
|
TTL: "2025-07-31T14:22:57.028000",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
EntryCount: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByID(t *testing.T) {
|
||||||
|
actual := audits.FilterByID("550e8400-e29b-41d4-a716-446655440002").FindOne()
|
||||||
|
|
||||||
|
if actual.GUID != "550e8400-e29b-41d4-a716-446655440002" {
|
||||||
|
t.Fatal("expected GUID 550e8400-e29b-41d4-a716-446655440002, found: ", actual.GUID)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByID("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByCorrelationID(t *testing.T) {
|
||||||
|
actual := audits.FilterByCorrelationID("550e8400-e29b-41d4-a716-446655440002").FindOne()
|
||||||
|
|
||||||
|
if actual.CorrelationID != "550e8400-e29b-41d4-a716-446655440002" {
|
||||||
|
t.Fatal("expected GUID 550e8400-e29b-41d4-a716-446655440002, found: ", actual.CorrelationID)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByCorrelationID("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByRemoteAddr(t *testing.T) {
|
||||||
|
actual := audits.FilterByRemoteAddr("192.168.1.100").FindOne()
|
||||||
|
|
||||||
|
if actual.RemoteAddr != "192.168.1.100" {
|
||||||
|
t.Fatal("expected remote address 192.168.1.100, found: ", actual.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByRemoteAddr("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByUser(t *testing.T) {
|
||||||
|
actual := audits.FilterByUser("test@example.com").FindOne()
|
||||||
|
|
||||||
|
if actual.User != "test@example.com" {
|
||||||
|
t.Fatal("expected user test@example.com, found: ", actual.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
actualEmpty := audits.FilterByUser("")
|
||||||
|
|
||||||
|
if len(actualEmpty.Data) != 0 {
|
||||||
|
t.Fatal("expected empty, actual: ", len(actualEmpty.Data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByCall(t *testing.T) {
|
||||||
|
actual := audits.FilterByCall("/restmachine/cloudapi/audit/test").FindOne()
|
||||||
|
|
||||||
|
if actual.Call != "/restmachine/cloudapi/audit/test" {
|
||||||
|
t.Fatal("expected call /restmachine/cloudapi/audit/test, found: ", actual.Call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterByStatusCode(t *testing.T) {
|
||||||
|
actual := audits.FilterByStatusCode(200)
|
||||||
|
|
||||||
|
for _, item := range actual.Data {
|
||||||
|
if item.StatusCode != 200 {
|
||||||
|
t.Fatal("expected 200 status code, found: ", item.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,6 +50,50 @@ type ListRequest struct {
|
|||||||
// Page size
|
// Page size
|
||||||
// Required: false
|
// Required: false
|
||||||
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
||||||
|
|
||||||
|
// Find by resource group id
|
||||||
|
// Required: false
|
||||||
|
RGID uint64 `url:"resgroup_id,omitempty" json:"resgroup_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by compute id
|
||||||
|
// Required: false
|
||||||
|
ComputeID uint64 `url:"compute_id,omitempty" json:"compute_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by account id
|
||||||
|
// Required: false
|
||||||
|
AccountID uint64 `url:"account_id,omitempty" json:"account_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by vins id
|
||||||
|
// Required: false
|
||||||
|
VINSID uint64 `url:"vins_id,omitempty" json:"vins_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by service id
|
||||||
|
// Required: false
|
||||||
|
ServiceID uint64 `url:"service_id,omitempty" json:"service_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by k8s id
|
||||||
|
// Required: false
|
||||||
|
K8SID uint64 `url:"k8s_id,omitempty" json:"k8s_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by flipgroup id
|
||||||
|
// Required: false
|
||||||
|
FLIPGroupID uint64 `url:"flipgroup_id,omitempty" json:"flipgroup_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by load balancer id
|
||||||
|
// Required: false
|
||||||
|
LBID uint64 `url:"lb_id,omitempty" json:"lb_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by sep id
|
||||||
|
// Required: false
|
||||||
|
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
|
||||||
|
|
||||||
|
// Find by node id
|
||||||
|
// Required: false
|
||||||
|
NodeID uint64 `url:"node_id,omitempty" json:"node_id,omitempty"`
|
||||||
|
|
||||||
|
// Exclude audit lines from response
|
||||||
|
// Required: false
|
||||||
|
ExcludeAuditLines bool `url:"exclude_audit_lines,omitempty" json:"exclude_audit_lines,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List gets audit records for the specified account object
|
// List gets audit records for the specified account object
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ type ItemAudit struct {
|
|||||||
|
|
||||||
// TTL
|
// TTL
|
||||||
TTL string `json:"_ttl"`
|
TTL string `json:"_ttl"`
|
||||||
|
|
||||||
// Tags
|
|
||||||
Tags string `json:"tags"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of audits
|
// List of audits
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ type DiskAddRequest struct {
|
|||||||
// Specify image id for create disk from template
|
// Specify image id for create disk from template
|
||||||
// Required: false
|
// Required: false
|
||||||
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
|
ImageID uint64 `url:"imageId,omitempty" json:"imageId,omitempty"`
|
||||||
|
|
||||||
|
// Desired PCI slot (hex string, e.g. "0x1A")
|
||||||
|
// Required: false
|
||||||
|
PCISlot string `url:"pci_slot,omitempty" json:"pci_slot,omitempty"`
|
||||||
|
|
||||||
|
// Desired bus number (hex string, e.g. "0x03")
|
||||||
|
// Required: false
|
||||||
|
BusNumber string `url:"bus_number,omitempty" json:"bus_number,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskAdd creates new disk and attach to compute
|
// DiskAdd creates new disk and attach to compute
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ type DiskAttachRequest struct {
|
|||||||
// Type of the disk B;D
|
// Type of the disk B;D
|
||||||
// Required: false
|
// Required: false
|
||||||
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty"`
|
DiskType string `url:"diskType,omitempty" json:"diskType,omitempty"`
|
||||||
|
|
||||||
|
// Desired PCI slot (hex string, e.g. "0x1A")
|
||||||
|
// Required: false
|
||||||
|
PCISlot string `url:"pci_slot,omitempty" json:"pci_slot,omitempty"`
|
||||||
|
|
||||||
|
// Desired bus number (hex string, e.g. "0x03")
|
||||||
|
// Required: false
|
||||||
|
BusNumber string `url:"bus_number,omitempty" json:"bus_number,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskAttach attach disk to compute
|
// DiskAttach attach disk to compute
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type MigrateStorageListRequest struct {
|
|||||||
|
|
||||||
// Sort by one of supported fields, format +|-(field)
|
// Sort by one of supported fields, format +|-(field)
|
||||||
// Required: false
|
// Required: false
|
||||||
SortBy string `url:"sortBy,omitempty" json:"sortBy,omitempty" validate:"omitempty,sortBy"`
|
SortBy string `url:"sort_by,omitempty" json:"sort_by,omitempty" validate:"omitempty,sortBy"`
|
||||||
|
|
||||||
// Page number
|
// Page number
|
||||||
// Required: false
|
// Required: false
|
||||||
|
|||||||
@@ -373,9 +373,18 @@ type ItemDisk struct {
|
|||||||
// Bus number
|
// Bus number
|
||||||
BusNumber uint64 `json:"bus_number"`
|
BusNumber uint64 `json:"bus_number"`
|
||||||
|
|
||||||
|
// Created by
|
||||||
|
CreatedBy string `json:"createdBy"`
|
||||||
|
|
||||||
// Created time
|
// Created time
|
||||||
CreatedTime uint64 `json:"createdTime"`
|
CreatedTime uint64 `json:"createdTime"`
|
||||||
|
|
||||||
|
// Device name
|
||||||
|
DeviceName string `json:"devicename"`
|
||||||
|
|
||||||
|
// Deleted by
|
||||||
|
DeletedBy string `json:"deletedBy"`
|
||||||
|
|
||||||
// Deleted time
|
// Deleted time
|
||||||
DeletedTime uint64 `json:"deletedTime"`
|
DeletedTime uint64 `json:"deletedTime"`
|
||||||
|
|
||||||
@@ -495,6 +504,9 @@ type ItemDisk struct {
|
|||||||
|
|
||||||
// Updated by
|
// Updated by
|
||||||
UpdatedBy string `json:"updatedBy"`
|
UpdatedBy string `json:"updatedBy"`
|
||||||
|
|
||||||
|
// UpdatedTime
|
||||||
|
UpdatedTime uint64 `json:"updatedTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ItemReplication struct {
|
type ItemReplication struct {
|
||||||
@@ -980,12 +992,15 @@ type RecordCompute struct {
|
|||||||
// Image ID
|
// Image ID
|
||||||
ImageID uint64 `json:"imageId"`
|
ImageID uint64 `json:"imageId"`
|
||||||
|
|
||||||
// ImageName
|
// Image name
|
||||||
ImageName string `json:"imageName"`
|
ImageName string `json:"imageName"`
|
||||||
|
|
||||||
// List interfaces
|
// List interfaces
|
||||||
Interfaces ListInterfaces `json:"interfaces"`
|
Interfaces ListInterfaces `json:"interfaces"`
|
||||||
|
|
||||||
|
// Loader meta iso information
|
||||||
|
LoaderMetaIso LoaderMetaIso `json:"loaderMetaIso"`
|
||||||
|
|
||||||
// Live migration job ID
|
// Live migration job ID
|
||||||
LiveMigrationJobID uint64 `json:"live_migration_job_id"`
|
LiveMigrationJobID uint64 `json:"live_migration_job_id"`
|
||||||
|
|
||||||
@@ -1125,6 +1140,14 @@ type RecordCompute struct {
|
|||||||
ZoneID uint64 `json:"zoneId"`
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LoaderMetaIso struct {
|
||||||
|
// Name
|
||||||
|
DeviceName string `json:"devicename"`
|
||||||
|
|
||||||
|
// Path
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
type VGPUItem struct {
|
type VGPUItem struct {
|
||||||
// ID
|
// ID
|
||||||
ID uint64 `json:"id"`
|
ID uint64 `json:"id"`
|
||||||
|
|||||||
58
pkg/cloudbroker/compute/start_migration_out.go
Normal file
58
pkg/cloudbroker/compute/start_migration_out.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StartMigrationOutRequest struct to start compute for external migration out
|
||||||
|
type StartMigrationOutRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"compute_id" json:"compute_id" validate:"required"`
|
||||||
|
|
||||||
|
// Remote libvirt host to connect to
|
||||||
|
// Required: true
|
||||||
|
Target string `url:"target" json:"target" validate:"required"`
|
||||||
|
|
||||||
|
// Graphics handling on the destination
|
||||||
|
// Required: true
|
||||||
|
Graphics string `url:"graphics" json:"graphics" validate:"required"`
|
||||||
|
|
||||||
|
// Optional new domain name on the destination
|
||||||
|
// Required: false
|
||||||
|
NewName string `url:"new_name,omitempty" json:"new_name,omitempty"`
|
||||||
|
|
||||||
|
// When true, adds libvirt's UNSAFE flag to force migration even if libvirt marks it unsafe.
|
||||||
|
// Default: false
|
||||||
|
// Required: false
|
||||||
|
UseUnsafe bool `url:"use_unsafe,omitempty" json:"use_unsafe,omitempty"`
|
||||||
|
|
||||||
|
// Mapping of guest disk target names to absolute paths on the destination host.
|
||||||
|
// Required: false
|
||||||
|
Diskmap map[string]string `url:"diskmap,omitempty" json:"diskmap,omitempty"`
|
||||||
|
|
||||||
|
// Mapping for CD/DVD devices or their source paths to new ISO/device paths on the destination
|
||||||
|
// Required: false
|
||||||
|
CDROMMap map[string]string `url:"cdrommap,omitempty" json:"cdrommap,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartMigrationOut starts compute for external migration out
|
||||||
|
func (c Compute) StartMigrationOut(ctx context.Context, req StartMigrationOutRequest) (string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/start_migration_out"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(res), nil
|
||||||
|
}
|
||||||
@@ -4,9 +4,26 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OSUsers struct contains OS user data for Guest OS.
|
||||||
|
// Must be provided if NewVMUUID is provided.
|
||||||
|
type OSUser struct {
|
||||||
|
// Login of a user
|
||||||
|
Login string `url:"login,omitempty" json:"login,omitempty"`
|
||||||
|
|
||||||
|
// Password of a user
|
||||||
|
Password string `url:"password,omitempty" json:"password,omitempty"`
|
||||||
|
|
||||||
|
// GUID
|
||||||
|
GUID string `url:"guid,omitempty" json:"guid,omitempty"`
|
||||||
|
|
||||||
|
// Pubkey
|
||||||
|
Pubkey string `url:"pubkey,omitempty" json:"pubkey,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// StopMigrationINRequest struct to stop compute for external migration in
|
// StopMigrationINRequest struct to stop compute for external migration in
|
||||||
type StopMigrationINRequest struct {
|
type StopMigrationINRequest struct {
|
||||||
// ID of compute instance
|
// ID of compute instance
|
||||||
@@ -16,10 +33,14 @@ type StopMigrationINRequest struct {
|
|||||||
// If provided, indicates the UUID of the VM on the target host and that migration completed.
|
// If provided, indicates the UUID of the VM on the target host and that migration completed.
|
||||||
// Required: false
|
// Required: false
|
||||||
NewVMUUID string `url:"new_vm_uuid,omitempty" json:"new_vm_uuid,omitempty"`
|
NewVMUUID string `url:"new_vm_uuid,omitempty" json:"new_vm_uuid,omitempty"`
|
||||||
|
|
||||||
|
// OS user data for Guest OS
|
||||||
|
// Required: false
|
||||||
|
OSUsers []OSUser `url:"os_users,omitempty" json:"os_users,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopMigrationIN stops compute for external migration in
|
// StopMigrationIN stops compute for external migration in
|
||||||
func (c Compute) StopMigrationIN(ctx context.Context, req StartRequest) (string, error) {
|
func (c Compute) StopMigrationIN(ctx context.Context, req StopMigrationINRequest) (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))
|
||||||
@@ -27,7 +48,7 @@ func (c Compute) StopMigrationIN(ctx context.Context, req StartRequest) (string,
|
|||||||
|
|
||||||
url := "/cloudbroker/compute/stop_migration_in"
|
url := "/cloudbroker/compute/stop_migration_in"
|
||||||
|
|
||||||
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 "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
37
pkg/cloudbroker/compute/stop_migration_out.go
Normal file
37
pkg/cloudbroker/compute/stop_migration_out.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package compute
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/constants"
|
||||||
|
"repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StopMigrationOutRequest struct to stop compute for external migration out
|
||||||
|
type StopMigrationOutRequest struct {
|
||||||
|
// ID of compute instance
|
||||||
|
// Required: true
|
||||||
|
ComputeID uint64 `url:"computeId" json:"computeId" validate:"required"`
|
||||||
|
|
||||||
|
// Identifier of the agent-side external migration (LibvirtMigrateToURI3Request) job
|
||||||
|
// Required: false
|
||||||
|
MigrateToURI3JobID string `url:"migrate_to_uri3_job_id,omitempty" json:"migrate_to_uri3_job_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopMigrationOut stops compute for external migration out
|
||||||
|
func (c Compute) StopMigrationOut(ctx context.Context, req StopMigrationOutRequest) (string, error) {
|
||||||
|
err := validators.ValidateRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", validators.ValidationErrors(validators.GetErrors(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
url := "/cloudbroker/compute/stop_migration_out"
|
||||||
|
|
||||||
|
res, err := c.client.DecortApiCallCtype(ctx, http.MethodPost, url, constants.MIMEJSON, req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(res), nil
|
||||||
|
}
|
||||||
@@ -30,10 +30,6 @@ type CreateRequest struct {
|
|||||||
// Required: false
|
// Required: false
|
||||||
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
Size uint64 `url:"size,omitempty" json:"size,omitempty"`
|
||||||
|
|
||||||
// Max IOPS disk can perform defaults to 2000
|
|
||||||
// Required: false
|
|
||||||
IOPS uint64 `url:"iops,omitempty" json:"iops,omitempty"`
|
|
||||||
|
|
||||||
// Storage endpoint provider ID to create disk
|
// Storage endpoint provider ID to create disk
|
||||||
// Required: false
|
// Required: false
|
||||||
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
|
SEPID uint64 `url:"sep_id,omitempty" json:"sep_id,omitempty"`
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ type ListRequest struct {
|
|||||||
// Find by enabled True or False
|
// Find by enabled True or False
|
||||||
// Required: false
|
// Required: false
|
||||||
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
Enabled interface{} `url:"enabled,omitempty" json:"enabled,omitempty" validate:"omitempty,isBool"`
|
||||||
|
|
||||||
|
// Find by storage policy id
|
||||||
|
// Required: false
|
||||||
|
StoragePolicyID uint64 `url:"storage_policy_id,omitempty" json:"storage_policy_id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List gets list of information about images as a ListImages struct
|
// List gets list of information about images as a ListImages struct
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ type ItemInterface struct {
|
|||||||
// Enabled
|
// Enabled
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Enable security groups
|
||||||
|
EnableSecGroups bool `json:"enable_secgroups"`
|
||||||
|
|
||||||
// FLIPGroup ID
|
// FLIPGroup ID
|
||||||
FLIPGroupID uint64 `json:"flipgroupId"`
|
FLIPGroupID uint64 `json:"flipgroupId"`
|
||||||
|
|
||||||
@@ -158,6 +161,9 @@ type ItemInterface struct {
|
|||||||
// NodeID
|
// NodeID
|
||||||
NodeID int64 `json:"nodeId"`
|
NodeID int64 `json:"nodeId"`
|
||||||
|
|
||||||
|
// List of security groups
|
||||||
|
SecGroups []uint64 `json:"security_groups"`
|
||||||
|
|
||||||
// SDNInterfaceID
|
// SDNInterfaceID
|
||||||
SDNInterfaceID string `json:"sdn_interface_id"`
|
SDNInterfaceID string `json:"sdn_interface_id"`
|
||||||
|
|
||||||
@@ -241,6 +247,9 @@ type VNFDev struct {
|
|||||||
|
|
||||||
// VNC password
|
// VNC password
|
||||||
VNCPassword string `json:"vncPasswd"`
|
VNCPassword string `json:"vncPasswd"`
|
||||||
|
|
||||||
|
// Zone ID
|
||||||
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main information about reservation
|
// Main information about reservation
|
||||||
@@ -421,6 +430,9 @@ type InfoVNF struct {
|
|||||||
|
|
||||||
// Type
|
// Type
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Zone ID
|
||||||
|
ZoneID uint64 `json:"zoneId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of static routes
|
// List of static routes
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ func getRequestsMapCloudAPI() map[string]interface{} {
|
|||||||
"/restmachine/cloudapi/account/updateUser": account.UpdateUserRequest{},
|
"/restmachine/cloudapi/account/updateUser": account.UpdateUserRequest{},
|
||||||
|
|
||||||
//audit
|
//audit
|
||||||
"/restmachine/cloudapi/audit/get": audit.GetRequest{},
|
"/restmachine/cloudapi/audit/get": audit.GetRequest{},
|
||||||
|
"/restmachine/cloudapi/audit/list": audit.ListRequest{},
|
||||||
|
|
||||||
//bservice
|
//bservice
|
||||||
"/restmachine/cloudapi/bservice/create": bservice.CreateRequest{},
|
"/restmachine/cloudapi/bservice/create": bservice.CreateRequest{},
|
||||||
|
|||||||
Reference in New Issue
Block a user