Compare commits

...

6 Commits

Author SHA1 Message Date
afcbc7e749 1.6.0-beta 2023-09-14 15:05:38 +03:00
0b3de4df7f 1.6.0-alfa 2023-09-11 13:11:33 +03:00
c0608d08b9 1.5.8-gostech 2023-09-07 18:11:25 +03:00
4d9b8fc9d8 v1.5.7 2023-09-04 18:48:22 +03:00
e8270453cc 1.5.6 2023-08-30 13:54:30 +03:00
7de095302b v1.5.5 2023-08-25 13:53:43 +03:00
15 changed files with 160 additions and 64 deletions

View File

@@ -1,9 +1,4 @@
## Version 1.5.4
### Feature
- Added cloudbroker/stack group of endpoints support. Added the possibility to get information about stacks (list handler) and about a specific stack by ID (get handler)
- Added cloudbroker/flipgroup group of endpoints support. Added the possibility to get information about flipgroup (list handler) and about a specific flipgroup by ID (get handler), add and remote compute, create, edit and delete flipgroup.
## Version 1.6.0-beta
### Bugfix
- Fixed the field image/models/history.guid, added a custom unmarshall. Fixed an error with get information about images (handlers - list, get) in cloudbroker
- Fixed RoudTrip bug in HTTP transport, made it concurrent safe

View File

@@ -3,6 +3,7 @@ package client
import (
"crypto/tls"
"net/http"
"sync"
"time"
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
@@ -32,6 +33,7 @@ func NewHttpClient(cfg config.Config) *http.Client {
ssoURL: cfg.SSOURL,
token: cfg.Token,
expiryTime: expiredTime,
mutex: &sync.Mutex{},
//TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},

View File

@@ -4,6 +4,7 @@ import (
"crypto/tls"
"net/http"
"net/url"
"sync"
"time"
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
@@ -33,6 +34,7 @@ func NewLegacyHttpClient(cfg config.LegacyConfig) *http.Client {
token: cfg.Token,
decortURL: cfg.DecortURL,
expiryTime: expiredTime,
mutex: &sync.Mutex{},
},
Timeout: cfg.Timeout.Get(),

View File

@@ -5,6 +5,7 @@ import (
"io"
"net/http"
"strings"
"sync"
"time"
)
@@ -15,6 +16,7 @@ type transportLegacy struct {
retries uint64
token string
decortURL string
mutex *sync.Mutex
expiryTime time.Time
}
@@ -56,7 +58,9 @@ func (t *transportLegacy) RoundTrip(request *http.Request) (*http.Response, erro
var resp *http.Response
var err error
for i := uint64(0); i < t.retries; i++ {
t.mutex.Lock()
resp, err = t.base.RoundTrip(req)
t.mutex.Unlock()
if err == nil {
if resp.StatusCode == 200 {
return resp, nil

View File

@@ -5,6 +5,7 @@ import (
"io"
"net/http"
"strings"
"sync"
"time"
)
@@ -16,6 +17,7 @@ type transport struct {
token string
ssoURL string
expiryTime time.Time
mutex *sync.Mutex
}
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
@@ -53,7 +55,9 @@ func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
var resp *http.Response
var err error
for i := uint64(0); i < t.retries; i++ {
t.mutex.Lock()
resp, err = t.base.RoundTrip(req)
t.mutex.Unlock()
if err == nil {
if resp.StatusCode == 200 {
return resp, nil
@@ -65,5 +69,6 @@ func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
//logrus.Errorf("Could not execute request: %v. Retrying %d/%d", err, i+1, t.retries)
time.Sleep(time.Second * 5)
}
return nil, fmt.Errorf("could not execute request: %w", err)
}

View File

@@ -106,6 +106,10 @@ type CreateRequest struct {
// Text description of this Kubernetes cluster
// Required: false
Description string `url:"desc,omitempty" json:"desc,omitempty"`
//Use only selected ExtNet for infrastructure connections
// Required: false
ExtNetOnly bool `url:"extnetOnly,omitempty" json:"extnetOnly,omitempty"`
}
// Create creates a new Kubernetes cluster in the specified Resource Group

View File

@@ -2,6 +2,7 @@ package lb
import (
"context"
"errors"
"net/http"
"strings"
@@ -20,16 +21,16 @@ type CreateRequest struct {
Name string `url:"name" json:"name" validate:"required"`
// External network to connect this load balancer to
// Required: true
ExtNetID uint64 `url:"extnetId" json:"extnetId" validate:"required"`
// Required: false
ExtNetID uint64 `url:"extnetId" json:"extnetId"`
// Internal network (VINS) to connect this load balancer to
// Required: true
VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"`
// Required: false
VINSID uint64 `url:"vinsId" json:"vinsId"`
// Start now Load balancer
// Required: true
Start bool `url:"start" json:"start" validate:"required"`
// Required: false
Start bool `url:"start" json:"start"`
// Text description of this load balancer
// Required: false
@@ -45,6 +46,10 @@ func (l LB) Create(ctx context.Context, req CreateRequest) (string, error) {
}
}
if req.ExtNetID == 0 && req.VINSID == 0 {
return "", errors.New ("vinsId and extNetId cannot be both in the value 0")
}
url := "/cloudapi/lb/create"
res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req)

View File

@@ -2,7 +2,7 @@ package grid
// FilterByID returns ListGrids with specified ID.
func (lg ListGrids) FilterByID(id uint64) ListGrids {
predicate := func(rg RecordGrid) bool {
predicate := func(rg ItemGridList) bool {
return rg.ID == id
}
@@ -11,7 +11,7 @@ func (lg ListGrids) FilterByID(id uint64) ListGrids {
// FilterByName returns ListGrids with specified Name.
func (lg ListGrids) FilterByName(name string) ListGrids {
predicate := func(rg RecordGrid) bool {
predicate := func(rg ItemGridList) bool {
return rg.Name == name
}
@@ -20,7 +20,7 @@ func (lg ListGrids) FilterByName(name string) ListGrids {
// FilterByLocationCode returns ListGrids with specified LocationCode.
func (lg ListGrids) FilterByLocationCode(locationCode string) ListGrids {
predicate := func(rg RecordGrid) bool {
predicate := func(rg ItemGridList) bool {
return rg.LocationCode == locationCode
}
@@ -28,7 +28,7 @@ func (lg ListGrids) FilterByLocationCode(locationCode string) ListGrids {
}
// FilterFunc allows filtering ListGrids based on a user-specified predicate.
func (lg ListGrids) FilterFunc(predicate func(RecordGrid) bool) ListGrids {
func (lg ListGrids) FilterFunc(predicate func(ItemGridList) bool) ListGrids {
var result ListGrids
for _, item := range lg.Data {
@@ -44,9 +44,9 @@ func (lg ListGrids) FilterFunc(predicate func(RecordGrid) bool) ListGrids {
// FindOne returns first found RecordGrid.
// If none was found, returns an empty struct.
func (lg ListGrids) FindOne() RecordGrid {
func (lg ListGrids) FindOne() ItemGridList {
if len(lg.Data) == 0 {
return RecordGrid{}
return ItemGridList{}
}
return lg.Data[0]

View File

@@ -3,7 +3,7 @@ package grid
import "testing"
var grids = ListGrids{
Data: []RecordGrid{
Data: []ItemGridList{
{
Resources: Resources{
Current: RecordResource{
@@ -123,7 +123,7 @@ func TestFilterByLocationCode(t *testing.T) {
}
func TestFilterFunc(t *testing.T) {
actual := grids.FilterFunc(func(rg RecordGrid) bool {
actual := grids.FilterFunc(func(rg ItemGridList) bool {
return rg.GID == 777
}).
FindOne()

View File

@@ -18,7 +18,7 @@ type RecordResourcesConsumption struct {
Reserved RecordResource `json:"Reserved"`
// GID
GID uint64 `json:"gid"`
GID uint64 `json:"id"`
}
type ListResourceConsumption struct {
@@ -67,6 +67,27 @@ type DiskUsage struct {
// Detailed information about grid
type RecordGrid struct {
// Flag
Flag string `json:"flag"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Location code
LocationCode string `json:"locationCode"`
// Name
Name string `json:"name"`
}
// Information about grid
type ItemGridList struct {
// Resource information
Resources Resources `json:"Resources"`
@@ -92,7 +113,7 @@ type RecordGrid struct {
// List Grids
type ListGrids struct {
//Data
Data []RecordGrid `json:"data"`
Data []ItemGridList `json:"data"`
// Entry count
EntryCount uint64 `json:"entryCount"`

View File

@@ -29,7 +29,7 @@ type CreateRequest struct {
// Start now Load balancer
// Required: false
Start bool `url:"start" json:"start" validate:"required"`
Start bool `url:"start" json:"start"`
// Text description of this load balancer
// Required: false

View File

@@ -9,7 +9,7 @@ import (
// FilterByID returns ListLB with specified ID.
func (ll ListLB) FilterByID(id uint64) ListLB {
predicate := func(rlb RecordLB) bool {
predicate := func(rlb ItemLBList) bool {
return rlb.ID == id
}
@@ -18,7 +18,7 @@ func (ll ListLB) FilterByID(id uint64) ListLB {
// FilterByName returns ListLB with specified Name.
func (ll ListLB) FilterByName(name string) ListLB {
predicate := func(rlb RecordLB) bool {
predicate := func(rlb ItemLBList) bool {
return rlb.Name == name
}
@@ -27,22 +27,13 @@ func (ll ListLB) FilterByName(name string) ListLB {
// FilterByExtNetID returns ListLB with specified ExtNetID.
func (ll ListLB) FilterByExtNetID(extNetID uint64) ListLB {
predicate := func(rlb RecordLB) bool {
predicate := func(rlb ItemLBList) bool {
return rlb.ExtNetID == extNetID
}
return ll.FilterFunc(predicate)
}
// FilterByImageID returns ListLB with specified ImageID.
func (ll ListLB) FilterByImageID(imageID uint64) ListLB {
predicate := func(rlb RecordLB) bool {
return rlb.ImageID == imageID
}
return ll.FilterFunc(predicate)
}
// FilterByK8SID returns ListLB used by specified K8S cluster.
func (ll ListLB) FilterByK8SID(ctx context.Context, k8sID uint64, decortClient interfaces.Caller) (*ListLB, error) {
caller := k8s.New(decortClient)
@@ -56,7 +47,7 @@ func (ll ListLB) FilterByK8SID(ctx context.Context, k8sID uint64, decortClient i
return nil, err
}
predicate := func(rlb RecordLB) bool {
predicate := func(rlb ItemLBList) bool {
return cluster.LBID == rlb.ID
}
@@ -66,7 +57,7 @@ func (ll ListLB) FilterByK8SID(ctx context.Context, k8sID uint64, decortClient i
}
// FilterFunc allows filtering ListLB based on a user-specified predicate.
func (ll ListLB) FilterFunc(predicate func(RecordLB) bool) ListLB {
func (ll ListLB) FilterFunc(predicate func(ItemLBList) bool) ListLB {
var result ListLB
for _, item := range ll.Data {
@@ -82,9 +73,9 @@ func (ll ListLB) FilterFunc(predicate func(RecordLB) bool) ListLB {
// FindOne returns first found RecordLB
// If none was found, returns an empty struct.
func (ll ListLB) FindOne() RecordLB {
func (ll ListLB) FindOne() ItemLBList {
if len(ll.Data) == 0 {
return RecordLB{}
return ItemLBList{}
}
return ll.Data[0]

View File

@@ -3,11 +3,9 @@ package lb
import "testing"
var lbs = ListLB{
Data: []RecordLB{
Data: []ItemLBList{
{
HAMode: true,
CKey: "",
Meta: []interface{}{},
ACL: []interface{}{},
Backends: []ItemBackend{},
CreatedBy: "test_user_1",
@@ -22,7 +20,6 @@ var lbs = ListLB{
GID: 212,
GUID: 1,
ID: 1,
ImageID: 2121,
Milestones: 129000,
Name: "k8s-lb-test-1",
PrimaryNode: Node{},
@@ -37,8 +34,6 @@ var lbs = ListLB{
},
{
HAMode: false,
CKey: "",
Meta: []interface{}{},
ACL: []interface{}{},
Backends: []ItemBackend{},
CreatedBy: "test_user_2",
@@ -53,7 +48,6 @@ var lbs = ListLB{
GID: 212,
GUID: 2,
ID: 2,
ImageID: 2129,
Milestones: 129013,
Name: "k8s-lb-test-2",
PrimaryNode: Node{},
@@ -68,8 +62,6 @@ var lbs = ListLB{
},
{
HAMode: true,
CKey: "",
Meta: []interface{}{},
ACL: []interface{}{},
Backends: []ItemBackend{},
CreatedBy: "te2t_user_3",
@@ -84,7 +76,6 @@ var lbs = ListLB{
GID: 212,
GUID: 3,
ID: 3,
ImageID: 2139,
Milestones: 129025,
Name: "k8s-lb-test-3",
PrimaryNode: Node{},
@@ -125,16 +116,8 @@ func TestFilterByExtNetID(t *testing.T) {
}
}
func TestFilterByImageID(t *testing.T) {
actual := lbs.FilterByImageID(2139).FindOne()
if actual.ImageID != 2139 {
t.Fatal("expected ImageID 2139, found: ", actual.ImageID)
}
}
func TestFilterFunc(t *testing.T) {
actual := lbs.FilterFunc(func(rl RecordLB) bool {
actual := lbs.FilterFunc(func(rl ItemLBList) bool {
return rl.Status == "DISABLED"
})

View File

@@ -136,7 +136,7 @@ type Node struct {
// List of load balancers
type ListLB struct {
// Data
Data []RecordLB `json:"data"`
Data []ItemLBList `json:"data"`
// Entry count
EntryCount uint64 `json:"entryCount"`
@@ -159,6 +159,69 @@ type RecordLB struct {
// List of load balancer backends
Backends ListBackends `json:"backends"`
// Description
Description string `json:"desc"`
// DPAPI password
DPAPIPassword string `json:"dpApiPassword"`
// DPAPI user
DPAPIUser string `json:"dpApiUser"`
// External network ID
ExtNetID uint64 `json:"extnetId"`
// List of load balancer frontends
Frontends ListFrontends `json:"frontends"`
// Grid ID
GID uint64 `json:"gid"`
// GUID
GUID uint64 `json:"guid"`
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// Milestones
Milestones uint64 `json:"milestones"`
// Name
Name string `json:"name"`
// Primary node
PrimaryNode Node `json:"primaryNode"`
// Resource group ID
RGID uint64 `json:"rgId"`
// Secondary node
SecondaryNode Node `json:"secondaryNode"`
// Status
Status string `json:"status"`
// Tech status
TechStatus string `json:"techStatus"`
// VINS ID
VINSID uint64 `json:"vinsId"`
}
// Detailed information about load balancer in List
type ItemLBList struct {
// HAMode
HAMode bool `json:"HAmode"`
// Access Control List
ACL []interface{} `json:"acl"`
// List of load balancer backends
Backends ListBackends `json:"backends"`
// Created by
CreatedBy string `json:"createdBy"`
@@ -195,9 +258,6 @@ type RecordLB struct {
// ID
ID uint64 `json:"id"`
// Image ID
ImageID uint64 `json:"imageId"`
// Milestones
Milestones uint64 `json:"milestones"`

View File

@@ -24,10 +24,31 @@ type Total struct {
UsageLimit uint64 `json:"usage_limit"`
}
type ByPool struct {
// Disk count
DiskCount uint64 `json:"disk_count"`
// Disk usage
DiskUsage uint64 `json:"disk_usage"`
// Snapshot count
SnapshotCount uint64 `json:"snapshot_count"`
// Snapshot usage
SnapshotUsage uint64 `json:"snapshot_usage"`
// Usage
Usage uint64 `json:"usage"`
// Usage limit
UsageLimit uint64 `json:"usage_limit"`
}
// Main information about consumption
type RecordConsumption struct {
// By pool
ByPool map[string]interface{} `json:"byPool"`
ByPool map[string]ByPool `json:"byPool"`
// Total resource information
Total Total `json:"total"`
@@ -70,6 +91,9 @@ type RecordPool struct {
// List URIs
URIs ListURIs `json:"uris"`
// Usage Limit
UsageLimit uint64 `json:"usage_limit"`
}
// SEP config