From 9f5e76aee48d0b9bb71fbbd0fab9a4b4b41720f2 Mon Sep 17 00:00:00 2001 From: stSolo Date: Sun, 24 Sep 2023 12:11:31 +0300 Subject: [PATCH] 1.6.0-delta --- .gitignore | 4 +- CHANGELOG.md | 14 +--- client.go | 16 ++-- config/config.go | 2 +- config/legacy-config.go | 2 +- config/timeouts.go | 4 +- legacy-client.go | 16 ++-- pkg/cloudapi/bservice/group_add.go | 4 + pkg/cloudapi/k8s/create.go | 81 +++++++++++++++++++ .../k8s/get_worker_nodes_meta_data.go | 38 +++++++++ pkg/cloudapi/k8s/models.go | 3 + .../k8s/update_worker_nodes_meta_data.go | 48 +++++++++++ pkg/cloudapi/lb/create.go | 70 +++++++++++++--- pkg/cloudapi/lb/frontend_bind.go | 10 +-- pkg/cloudapi/lb/frontend_bind_update.go | 8 +- pkg/cloudapi/lb/make_highly_available.go | 40 +++++++++ pkg/cloudapi/lb/models.go | 14 +++- pkg/cloudapi/lb/updateSysctParams.go | 72 +++++++++++++++++ pkg/cloudapi/stack.go | 10 +++ pkg/cloudapi/stack/get.go | 42 ++++++++++ pkg/cloudapi/stack/list.go | 53 ++++++++++++ pkg/cloudapi/stack/models.go | 53 ++++++++++++ pkg/cloudapi/stack/stack.go | 16 ++++ pkg/cloudapi/vins/create_in_account.go | 45 ++++++++++- pkg/cloudapi/vins/create_in_rg.go | 34 +++++++- pkg/cloudapi/vins/models.go | 45 +++++++++++ pkg/cloudapi/vins/staticRouteList.go | 42 ++++++++++ .../vins/static_route_access_grant.go | 48 +++++++++++ .../vins/static_route_access_revoke.go | 48 +++++++++++ pkg/cloudapi/vins/static_route_add.go | 56 +++++++++++++ pkg/cloudapi/vins/static_route_del.go | 44 ++++++++++ 31 files changed, 924 insertions(+), 58 deletions(-) create mode 100644 pkg/cloudapi/k8s/get_worker_nodes_meta_data.go create mode 100644 pkg/cloudapi/k8s/update_worker_nodes_meta_data.go create mode 100644 pkg/cloudapi/lb/make_highly_available.go create mode 100644 pkg/cloudapi/lb/updateSysctParams.go create mode 100644 pkg/cloudapi/stack.go create mode 100644 pkg/cloudapi/stack/get.go create mode 100644 pkg/cloudapi/stack/list.go create mode 100644 pkg/cloudapi/stack/models.go create mode 100644 pkg/cloudapi/stack/stack.go create mode 100644 pkg/cloudapi/vins/staticRouteList.go create mode 100644 pkg/cloudapi/vins/static_route_access_grant.go create mode 100644 pkg/cloudapi/vins/static_route_access_revoke.go create mode 100644 pkg/cloudapi/vins/static_route_add.go create mode 100644 pkg/cloudapi/vins/static_route_del.go diff --git a/.gitignore b/.gitignore index 224dd8c..09215c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ cmd/ .idea/ -.vscode/ \ No newline at end of file +.vscode/ +.fleet/ +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eabf3e..dd743a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1 @@ -## Version 1.5.8 - -### Bugfix -- Fix model the RecordK8CI to cloudbroker/k8ci/models to correctly receive information on get request -- Add model the RecordK8CIList to cloudbroker/k8ci/models to correctly receive information on list request -- Refactored clients to fix the problems with concurrency safety -- Add the Routes field in the CreateInRGRequest and CreateInAccountRequest models in cb/vins. The fields for creating the resource are matched - -For get request to work correctly: -- Fix the Rules field (fix type) in the NATConfig model in cb/vins/models and ca/vins/models -- Fix the InfoVNF model (remove the excess field, add the Routes field) in cb/vins/models -- Add the ItemRoutes model in cb/vins/models -- Fix the RecordVINS model (remove the excess fields) in cb/vins/models +## Version 1.6.0-delta diff --git a/client.go b/client.go index a327d91..062c6f5 100644 --- a/client.go +++ b/client.go @@ -140,24 +140,24 @@ func (dc *DecortClient) do(req *http.Request) (*http.Response, error) { req.Header.Add("Authorization", "bearer "+dc.cfg.Token) req.Header.Set("Accept", "application/json") - var resp *http.Response - var err error + // var resp *http.Response + // var err error buf, _ := io.ReadAll(req.Body) - for i := uint64(0); i < dc.cfg.Retries; i++ { - req := req.Clone(req.Context()) + // for i := uint64(0); i < dc.cfg.Retries; i++ { + req = req.Clone(req.Context()) req.Body = io.NopCloser(bytes.NewBuffer(buf)) - resp, err = dc.client.Do(req) + resp, err := dc.client.Do(req) - if err == nil { + // if err == nil { if resp.StatusCode == 200 { return resp, err } respBytes, _ := io.ReadAll(resp.Body) err = fmt.Errorf("%s", respBytes) resp.Body.Close() - } - } + // } + // } return nil, fmt.Errorf("could not execute request: %w", err) } diff --git a/config/config.go b/config/config.go index f7dfc11..d6847ae 100644 --- a/config/config.go +++ b/config/config.go @@ -42,7 +42,7 @@ type Config struct { // Required: false Retries uint64 `json:"retries" yaml:"retries"` - // Skip verify, true by default + // Skip verify // Required: false SSLSkipVerify bool `json:"sslSkipVerify" yaml:"sslSkipVerify"` diff --git a/config/legacy-config.go b/config/legacy-config.go index 93b5495..a3a7a09 100644 --- a/config/legacy-config.go +++ b/config/legacy-config.go @@ -36,7 +36,7 @@ type LegacyConfig struct { // Required: false Retries uint64 `json:"retries" yaml:"retries"` - // Skip verify, true by default + // Skip verify // Required: false SSLSkipVerify bool `json:"sslSkipVerify" yaml:"sslSkipVerify"` diff --git a/config/timeouts.go b/config/timeouts.go index dd319e8..89a12eb 100644 --- a/config/timeouts.go +++ b/config/timeouts.go @@ -23,7 +23,7 @@ func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error { *d = Duration(tmp) return nil default: - return fmt.Errorf("Invalid duration %v", value) + return fmt.Errorf("invalid duration %v", value) } } @@ -41,7 +41,7 @@ func (d *Duration) UnmarshalJSON(b []byte) error { *d = Duration(tmp) return nil default: - return fmt.Errorf("Invalid duration %v", value) + return fmt.Errorf("invalid duration %v", value) } } diff --git a/legacy-client.go b/legacy-client.go index 6cb8996..c9849b1 100644 --- a/legacy-client.go +++ b/legacy-client.go @@ -137,24 +137,24 @@ func (ldc *LegacyDecortClient) do(req *http.Request) (*http.Response, error) { req.Header.Add("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") - var resp *http.Response - var err error + // var resp *http.Response + // var err error buf, _ := io.ReadAll(req.Body) - for i := uint64(0); i < ldc.cfg.Retries; i++ { - req := req.Clone(req.Context()) + // for i := uint64(0); i < ldc.cfg.Retries; i++ { + req = req.Clone(req.Context()) req.Body = io.NopCloser(bytes.NewBuffer(buf)) - resp, err = ldc.client.Do(req) + resp, err := ldc.client.Do(req) - if err == nil { + // if err == nil { if resp.StatusCode == 200 { return resp, err } respBytes, _ := io.ReadAll(resp.Body) err = fmt.Errorf("%s", respBytes) resp.Body.Close() - } - } + // } + // } return nil, fmt.Errorf("could not execute request: %w", err) } diff --git a/pkg/cloudapi/bservice/group_add.go b/pkg/cloudapi/bservice/group_add.go index 0df96b4..aa0ee41 100644 --- a/pkg/cloudapi/bservice/group_add.go +++ b/pkg/cloudapi/bservice/group_add.go @@ -68,6 +68,10 @@ type GroupAddRequest struct { // Time of Compute Group readiness // Required: false TimeoutStart uint64 `url:"timeoutStart,omitempty" json:"timeoutStart,omitempty"` + + // Meta data for working group computes, format YAML "user_data": 1111 + // Required: false + UserData string `url:"userData,omitempty" json:"userData,omitempty"` } // GroupAdd creates new Compute Group within BasicService. diff --git a/pkg/cloudapi/k8s/create.go b/pkg/cloudapi/k8s/create.go index d00edcf..49962d4 100644 --- a/pkg/cloudapi/k8s/create.go +++ b/pkg/cloudapi/k8s/create.go @@ -8,6 +8,8 @@ import ( "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" ) +// type Params []string + // Request struct for create kubernetes cluster type CreateRequest struct { // Name of Kubernetes cluster @@ -98,16 +100,73 @@ type CreateRequest struct { // Required: false ExtNetID uint64 `url:"extnetId,omitempty" json:"extnetId,omitempty"` + // ID of the ViNS to connect k8s cluster. If nothing is specified, ViNS will be created automatically + // Required: false + VinsId uint64 `url:"vinsId,omitempty" json:"vinsId,omitempty"` + // Create Kubernetes cluster with masters nodes behind load balancer if true. // Otherwise give all cluster nodes direct external addresses from selected ExtNet // Required: false WithLB bool `url:"withLB" json:"withLB"` + // Custom sysctl values for Load Balancer instance. Applied on boot + // Required: false + LbSysctlParams string `url:"-" json:"lbSysctlParams,omitempty" validate:"omitempty,dive"` + + // Use Highly Available schema for LB deploy + // Required: false + HighlyAvailable bool `url:"highlyAvailable,omitempty" json:"highlyAvailable,omitempty"` + + // Optional extra Subject Alternative Names (SANs) to use for the API Server serving certificate. Can be both IP addresses and DNS names + // Required: false + AdditionalSANs []string `url:"additionalSANs,omitempty" json:"additionalSANs,omitempty"` + + // Is used to define settings and actions that should be performed before any other component in the cluster starts. + // It allows you to configure things like node registration, network setup, and other initialization tasks. insert a valid JSON string with all levels of nesting + // Required: false + InitConfiguration string `url:"initConfiguration,omitempty" json:"initConfiguration,omitempty"` + + // Is used to define global settings and configurations for the entire cluster. + // It includes parameters such as cluster name, DNS settings, authentication methods, and other cluster-wide configurations. + // Insert a valid JSON string with all levels of nesting + // Required: false + ClusterConfiguration string `url:"clusterConfiguration,omitempty" json:"clusterConfiguration,omitempty"` + + // Is used to configure the behavior and settings of the Kubelet, which is the primary node agent that runs on each node in the cluster. + // It includes parameters such as node IP address, resource allocation, pod eviction policies, and other Kubelet-specific configurations. + // Insert a valid JSON string with all levels of nesting + // Required: false + KubeletConfiguration string `url:"kubeletConfiguration,omitempty" json:"kubeletConfiguration,omitempty"` + + // Is used to configure the behavior and settings of the Kube-proxy, which is responsible for network proxying and load balancing within the cluster. + // It includes parameters such as proxy mode, cluster IP ranges, and other Kube-proxy specific configurations. + // Insert a valid JSON string with all levels of nesting + // Required: false + KubeProxyConfiguration string `url:"kubeProxyConfiguration,omitempty" json:"kubeProxyConfiguration,omitempty"` + + // Is used to configure the behavior and settings for joining a node to a cluster. + // It includes parameters such as the cluster's control plane endpoint, token, and certificate key. insert a valid JSON string with all levels of nesting + // Required: false + JoinConfiguration string `url:"joinConfiguration,omitempty" json:"joinConfiguration,omitempty"` + // Text description of this Kubernetes cluster // Required: false Description string `url:"desc,omitempty" json:"desc,omitempty"` + + // Meta data for working group computes, format YAML "user_data": 1111 + // Required: false + UserData string `url:"userData,omitempty" json:"userData,omitempty"` + + // Use only selected ExtNet for infrastructure connections + // Required: false + ExtNetOnly bool `url:"extnetOnly,omitempty" json:"extnetOnly,omitempty"` } +// type wrapperCreateRequest struct { +// CreateRequest +// Params []string `url:"lbSysctlParams,omitempty"` +// } + // Create creates a new Kubernetes cluster in the specified Resource Group func (k8s K8S) Create(ctx context.Context, req CreateRequest) (string, error) { err := validators.ValidateRequest(req) @@ -117,6 +176,28 @@ func (k8s K8S) Create(ctx context.Context, req CreateRequest) (string, error) { } } + // var params []string + + // if len(req.LbSysctlParams) != 0 { + // params = make([]string, 0, len(req.LbSysctlParams)) + + // for r := range req.LbSysctlParams { + // b, err := json.Marshal(req.LbSysctlParams[r]) + // if err != nil { + // return "", err + // } + + // params = append(params, string(b)) + // } + // } else { + // params = []string{"[]"} + // } + + // reqWrapped := wrapperCreateRequest{ + // CreateRequest: req, + // Params: params, + // } + url := "/cloudapi/k8s/create" res, err := k8s.client.DecortApiCall(ctx, http.MethodPost, url, req) diff --git a/pkg/cloudapi/k8s/get_worker_nodes_meta_data.go b/pkg/cloudapi/k8s/get_worker_nodes_meta_data.go new file mode 100644 index 0000000..69fb4a6 --- /dev/null +++ b/pkg/cloudapi/k8s/get_worker_nodes_meta_data.go @@ -0,0 +1,38 @@ +package k8s + +import ( + "context" + "net/http" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for get worker group metadata by ID +type GetWorkerNodesMetaDataRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"` + + // ID of the workers compute group + // Required: true + WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"` +} + +// Get worker group metadata by ID +func (k K8S) GetWorkerNodesMetaData(ctx context.Context, req GetWorkerNodesMetaDataRequest) (string, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return "", validators.ValidationError(validationError) + } + } + + url := "/cloudapi/k8s/getWorkerNodesMetaData" + + res, err := k.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return "", err + } + + return string(res), nil +} diff --git a/pkg/cloudapi/k8s/models.go b/pkg/cloudapi/k8s/models.go index a4b6cd9..e01723c 100644 --- a/pkg/cloudapi/k8s/models.go +++ b/pkg/cloudapi/k8s/models.go @@ -41,6 +41,9 @@ type ListK8SGroups []ItemK8SGroup // Detailed information type ItemDetailedInfo struct { + // Externalip + Externalip string `json:"externalip"` + // ID ID uint64 `json:"id"` diff --git a/pkg/cloudapi/k8s/update_worker_nodes_meta_data.go b/pkg/cloudapi/k8s/update_worker_nodes_meta_data.go new file mode 100644 index 0000000..42ca590 --- /dev/null +++ b/pkg/cloudapi/k8s/update_worker_nodes_meta_data.go @@ -0,0 +1,48 @@ +package k8s + +import ( + "context" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for add worker to a kubernetes cluster +type UpdateWorkerNodesMetaDataRequest struct { + // Kubernetes cluster ID + // Required: true + K8SID uint64 `url:"k8sId" json:"k8sId" validate:"required"` + + // ID of the workers compute group + // Required: true + WorkersGroupID uint64 `url:"workersGroupId" json:"workersGroupId" validate:"required"` + + // Meta data for working group computes, format YAML "user_data": 1111 + // Required: true + UserData string `url:"userData" json:"userData" validate:"required"` +} + +// WorkerAdd adds worker nodes to a kubernetes cluster +func (k K8S) UpdateWorkerNodesMetaData(ctx context.Context, req UpdateWorkerNodesMetaDataRequest) (bool, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return false, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/k8s/updateWorkerNodesMetaData" + + res, err := k.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 +} diff --git a/pkg/cloudapi/lb/create.go b/pkg/cloudapi/lb/create.go index e437882..d2d637e 100644 --- a/pkg/cloudapi/lb/create.go +++ b/pkg/cloudapi/lb/create.go @@ -2,12 +2,16 @@ package lb import ( "context" + "encoding/json" + "errors" "net/http" - "strings" + "strconv" "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" ) +type Params []string + // Request struct for create load balancer type CreateRequest struct { // ID of the resource group where this load balancer instance will be located @@ -20,39 +24,81 @@ 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"` + + // Custom sysctl values for Load Balancer instance. Applied on boot + // Required: false + SysctlParams Params `url:"-" json:"sysctlParams,omitempty" validate:"omitempty,dive"` + + // Use Highly Available schema for LB deploy + // Required: false + HighlyAvailable bool `url:"highlyAvailable,omitempty" json:"highlyAvailable,omitempty"` // 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 Description string `url:"desc,omitempty" json:"desc,omitempty"` } +type wrapperCreateRequest struct { + CreateRequest + Params []string `url:"sysctlParams,omitempty"` +} + // Create method will create a new load balancer instance -func (l LB) Create(ctx context.Context, req CreateRequest) (string, error) { +func (l LB) Create(ctx context.Context, req CreateRequest) (uint64, error) { err := validators.ValidateRequest(req) if err != nil { for _, validationError := range validators.GetErrors(err) { - return "", validators.ValidationError(validationError) + return 0, validators.ValidationError(validationError) } } + if req.ExtNetID == 0 && req.VINSID == 0 { + return 0, errors.New("vinsId and extNetId cannot be both in the value 0") + } + + var params []string + + if len(req.SysctlParams) != 0 { + params = make([]string, 0, len(req.SysctlParams)) + + for r := range req.SysctlParams { + b, err := json.Marshal(req.SysctlParams[r]) + if err != nil { + return 0, err + } + + params = append(params, string(b)) + } + } else { + params = []string{} + } + + reqWrapped := wrapperCreateRequest{ + CreateRequest: req, + Params: params, + } + url := "/cloudapi/lb/create" - res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped) if err != nil { - return "", err + return 0, err } - result := strings.ReplaceAll(string(res), "\"", "") + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } return result, nil } diff --git a/pkg/cloudapi/lb/frontend_bind.go b/pkg/cloudapi/lb/frontend_bind.go index 86e6d14..f182dd4 100644 --- a/pkg/cloudapi/lb/frontend_bind.go +++ b/pkg/cloudapi/lb/frontend_bind.go @@ -20,18 +20,18 @@ type FrontendBindRequest struct { // Name of the binding to update // Required: true - BindingName string `url:"bindingName" json:"bindingName"` + BindingName string `url:"bindingName" json:"bindingName" validate:"required"` // If specified must be within the IP range of either Ext Net or ViNS, // where this load balancer is connected - new IP address to use for this binding. // If omitted, current IP address is retained - // Required: false - BindingAddress string `url:"bindingAddress,omitempty" json:"bindingAddress,omitempty"` + // Required: true + BindingAddress string `url:"bindingAddress" json:"bindingAddress" validate:"required"` // New port number to use for this binding. // If omitted, current port number is retained - // Required: false - BindingPort uint64 `url:"bindingPort,omitempty" json:"bindingPort,omitempty"` + // Required: true + BindingPort uint64 `url:"bindingPort" json:"bindingPort" validate:"required"` } // FrontendBind bind frontend from specified load balancer instance diff --git a/pkg/cloudapi/lb/frontend_bind_update.go b/pkg/cloudapi/lb/frontend_bind_update.go index 97e8d5e..54a6d69 100644 --- a/pkg/cloudapi/lb/frontend_bind_update.go +++ b/pkg/cloudapi/lb/frontend_bind_update.go @@ -25,13 +25,13 @@ type FrontendBindUpdateRequest struct { // If specified must be within the IP range of either Ext Net or ViNS, // where this load balancer is connected - new IP address to use for this binding. // If omitted, current IP address is retained - // Required: false - BindingAddress string `url:"bindingAddress,omitempty" json:"bindingAddress,omitempty"` + // Required: true + BindingAddress string `url:"bindingAddress" json:"bindingAddress" validate:"required"` // New port number to use for this binding. // If omitted, current port number is retained - // Required: false - BindingPort uint64 `url:"bindingPort,omitempty" json:"bindingPort,omitempty"` + // Required: true + BindingPort uint64 `url:"bindingPort" json:"bindingPort" validate:"required"` } // FrontendBindUpdate updates binding for the specified load balancer frontend diff --git a/pkg/cloudapi/lb/make_highly_available.go b/pkg/cloudapi/lb/make_highly_available.go new file mode 100644 index 0000000..ad2b88c --- /dev/null +++ b/pkg/cloudapi/lb/make_highly_available.go @@ -0,0 +1,40 @@ +package lb + +import ( + "context" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for make Load Balancer Highly available +type HighlyAvailableRequest struct { + // ID of the LB instance + // Required: true + LBID uint64 `url:"lbId" json:"lbId" validate:"required"` +} + +// Make Load Balancer Highly available +func (l LB) HighlyAvailable(ctx context.Context, req HighlyAvailableRequest) (uint64, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return 0, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/lb/makeHighlyAvailable" + + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return 0, err + } + + result, err := strconv.ParseUint(string(res), 10, 64) + if err != nil { + return 0, err + } + + return result, nil +} diff --git a/pkg/cloudapi/lb/models.go b/pkg/cloudapi/lb/models.go index 548dccf..fc503e0 100644 --- a/pkg/cloudapi/lb/models.go +++ b/pkg/cloudapi/lb/models.go @@ -6,7 +6,10 @@ type RecordLB struct { HAMode bool `json:"HAmode"` // Access Control List - ACL interface{} `json:"acl"` + ACL []interface{} `json:"acl"` + + // BackendHAIP + BackendHAIP string `json:"backendHAIP"` // List of load balancer backends Backends ListBackends `json:"backends"` @@ -32,6 +35,9 @@ type RecordLB struct { // External network ID ExtNetID uint64 `json:"extnetId"` + // FrontendHAIP + FrontendHAIP string `json:"frontendHAIP"` + // List of load balancer frontends Frontends ListFrontends `json:"frontends"` @@ -53,6 +59,9 @@ type RecordLB struct { // Name Name string `json:"name"` + // Part K8s + PartK8s bool `json:"partK8s"` + // Primary node PrimaryNode RecordNode `json:"primaryNode"` @@ -68,6 +77,9 @@ type RecordLB struct { // Status Status string `json:"status"` + // Sysctl Params + SysctlParams []interface{} `json:"sysctlParams"` + // Tech status TechStatus string `json:"techStatus"` diff --git a/pkg/cloudapi/lb/updateSysctParams.go b/pkg/cloudapi/lb/updateSysctParams.go new file mode 100644 index 0000000..d50ea95 --- /dev/null +++ b/pkg/cloudapi/lb/updateSysctParams.go @@ -0,0 +1,72 @@ +package lb + +import ( + "context" + "encoding/json" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for update sysct params for lb +type UpdateSysctParamsRequest struct { + // ID of the LB instance + // Required: true + LBID uint64 `url:"lbId" json:"lbId" validate:"required"` + + // Custom sysctl values for Load Balancer instance. Applied on boot + // Required: true + SysctlParams Params `url:"-" json:"sysctlParams" validate:"required,dive"` +} + +type wrapperUpdateSysctParamsRequest struct { + UpdateSysctParamsRequest + Params []string `url:"sysctlParams" validate:"required"` +} + +// Create method will create a new load balancer instance +func (l LB) UpdateSysctParams(ctx context.Context, req UpdateSysctParamsRequest) (bool, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return false, validators.ValidationError(validationError) + } + } + + var params []string + + if len(req.SysctlParams) != 0 { + params = make([]string, 0, len(req.SysctlParams)) + + for r := range req.SysctlParams { + b, err := json.Marshal(req.SysctlParams[r]) + if err != nil { + return false, err + } + + params = append(params, string(b)) + } + } else { + params = []string{} + } + + reqWrapped := wrapperUpdateSysctParamsRequest{ + UpdateSysctParamsRequest: req, + Params: params, + } + + url := "/cloudapi/lb/updateSysctParams" + + res, err := l.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped) + if err != nil { + return false, err + } + + result, err := strconv.ParseBool(string(res)) + if err != nil { + return false, err + } + + return result, nil +} diff --git a/pkg/cloudapi/stack.go b/pkg/cloudapi/stack.go new file mode 100644 index 0000000..2beabc4 --- /dev/null +++ b/pkg/cloudapi/stack.go @@ -0,0 +1,10 @@ +package cloudapi + +import ( + "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/stack" +) + +// Accessing the Stack method group +func (ca *CloudAPI) Stack() *stack.Stack { + return stack.New(ca.client) +} diff --git a/pkg/cloudapi/stack/get.go b/pkg/cloudapi/stack/get.go new file mode 100644 index 0000000..4c5d2a3 --- /dev/null +++ b/pkg/cloudapi/stack/get.go @@ -0,0 +1,42 @@ +package stack + +import ( + "context" + "encoding/json" + "net/http" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for get info of stack +type GetRequest struct { + // Find by ID + // Required: true + StackId uint64 `url:"stackId" json:"stackId" validate:"required"` +} + +// Get stack details by ID +func (i Stack) Get(ctx context.Context, req GetRequest) (*InfoStack, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return nil, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/stack/get" + + res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + info := InfoStack{} + + err = json.Unmarshal(res, &info) + if err != nil { + return nil, err + } + + return &info, nil +} diff --git a/pkg/cloudapi/stack/list.go b/pkg/cloudapi/stack/list.go new file mode 100644 index 0000000..a7afe75 --- /dev/null +++ b/pkg/cloudapi/stack/list.go @@ -0,0 +1,53 @@ +package stack + +import ( + "context" + "encoding/json" + "net/http" +) + +// Request struct for get list stack +type ListRequest struct { + // Find by ID + // Required: false + ByID uint64 `url:"by_id,omitempty" json:"by_id,omitempty"` + + // Find by name + // Required: false + Name string `url:"name,omitempty" json:"name,omitempty"` + + // Find by type + // Required: false + Type string `url:"type,omitempty" json:"type,omitempty"` + + // Find by status + // Required: false + Status string `url:"status,omitempty" json:"status,omitempty"` + + // Page number + // Required: false + Page uint64 `url:"page,omitempty" json:"page,omitempty"` + + // Page size + // Required: false + Size uint64 `url:"size,omitempty" json:"size,omitempty"` +} + +// ListStacks gets list stack +func (i Stack) List(ctx context.Context, req ListRequest) (*ListStacks, error) { + url := "/cloudapi/stack/list" + + res, err := i.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListStacks{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return &list, nil +} diff --git a/pkg/cloudapi/stack/models.go b/pkg/cloudapi/stack/models.go new file mode 100644 index 0000000..895344d --- /dev/null +++ b/pkg/cloudapi/stack/models.go @@ -0,0 +1,53 @@ +package stack + +// Main information about stack +type InfoStack struct { + // CPU allocation ratio + CPUAllocationRatio float64 `json:"cpu_allocation_ratio"` + + // Descr + Descr string `json:"descr"` + + // Drivers + Drivers []string `json:"drivers"` + + // ID + ID uint64 `json:"id"` + + // Mem allocation ratio + MemAllocationRatio float64 `json:"mem_allocation_ratio"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` +} + +// Information about stack in list +type ItemStack struct { + // ID + ID uint64 `json:"id"` + + // Name + Name string `json:"name"` + + // Status + Status string `json:"status"` + + // Type + Type string `json:"type"` +} + +// List of stacks +type ListStacks struct { + + //List + Data []ItemStack `json:"data"` + + //Entry count + EntryCount uint64 `json:"entryCount"` +} diff --git a/pkg/cloudapi/stack/stack.go b/pkg/cloudapi/stack/stack.go new file mode 100644 index 0000000..94c5d89 --- /dev/null +++ b/pkg/cloudapi/stack/stack.go @@ -0,0 +1,16 @@ +// Lists all the stack. +package stack + +import "repository.basistech.ru/BASIS/decort-golang-sdk/interfaces" + +// Structure for creating request to stack +type Stack struct { + client interfaces.Caller +} + +// Builder for stack endpoint +func New(client interfaces.Caller) *Stack { + return &Stack{ + client: client, + } +} diff --git a/pkg/cloudapi/vins/create_in_account.go b/pkg/cloudapi/vins/create_in_account.go index 2970dc7..d1b6dce 100644 --- a/pkg/cloudapi/vins/create_in_account.go +++ b/pkg/cloudapi/vins/create_in_account.go @@ -2,12 +2,24 @@ package vins import ( "context" + "encoding/json" "net/http" "strconv" "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" ) +type Route struct { + // Destination network + Destination string `url:"destination" json:"destination" validate:"required"` + + //Destination network mask in 255.255.255.255 format + Netmask string `url:"netmask" json:"netmask" validate:"required"` + + //Next hop host, IP address from ViNS ID free IP pool + Gateway string `url:"gateway" json:"gateway" validate:"required"` +} + // Request struct for create VINS in account type CreateInAccountRequest struct { // VINS name @@ -33,6 +45,15 @@ type CreateInAccountRequest struct { // Number of pre created reservations // Required: false PreReservationsNum uint64 `url:"preReservationsNum,omitempty" json:"preReservationsNum,omitempty"` + + // List of static routes, each item must have destination, netmask, and gateway fields + // Required: false + Routes []Route `url:"-" json:"routes,omitempty" validate:"omitempty,dive"` +} + +type wrapperCreateRequestInAcc struct { + CreateInAccountRequest + Routes []string `url:"routes,omitempty"` } // CreateInAccount creates VINS in account level @@ -44,9 +65,31 @@ func (v VINS) CreateInAccount(ctx context.Context, req CreateInAccountRequest) ( } } + var routes []string + + if len(req.Routes) != 0 { + routes = make([]string, 0, len(req.Routes)) + + for r := range req.Routes { + b, err := json.Marshal(req.Routes[r]) + if err != nil { + return 0, err + } + + routes = append(routes, string(b)) + } + } else { + routes = []string{} + } + + reqWrapped := wrapperCreateRequestInAcc{ + CreateInAccountRequest: req, + Routes: routes, + } + url := "/cloudapi/vins/createInAccount" - res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped) if err != nil { return 0, err } diff --git a/pkg/cloudapi/vins/create_in_rg.go b/pkg/cloudapi/vins/create_in_rg.go index c01f164..a71bcbb 100644 --- a/pkg/cloudapi/vins/create_in_rg.go +++ b/pkg/cloudapi/vins/create_in_rg.go @@ -2,6 +2,7 @@ package vins import ( "context" + "encoding/json" "net/http" "strconv" @@ -37,6 +38,15 @@ type CreateInRGRequest struct { // Number of pre created reservations // Required: false PreReservationsNum uint64 `url:"preReservationsNum,omitempty" json:"preReservationsNum,omitempty"` + + // List of static routes, each item must have destination, netmask, and gateway fields + // Required: false + Routes []Route `url:"-" json:"routes,omitempty" validate:"omitempty,dive"` +} + +type wrapperCreateRequestInRG struct { + CreateInRGRequest + Routes []string `url:"routes,omitempty"` } // CreateInRG creates VINS in resource group level @@ -48,9 +58,31 @@ func (v VINS) CreateInRG(ctx context.Context, req CreateInRGRequest) (uint64, er } } + var routes []string + + if len(req.Routes) != 0 { + routes = make([]string, 0, len(req.Routes)) + + for r := range req.Routes { + b, err := json.Marshal(req.Routes[r]) + if err != nil { + return 0, err + } + + routes = append(routes, string(b)) + } + } else { + routes = []string{} + } + + reqWrapped := wrapperCreateRequestInRG{ + CreateInRGRequest: req, + Routes: routes, + } + url := "/cloudapi/vins/createInRG" - res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, reqWrapped) if err != nil { return 0, err } diff --git a/pkg/cloudapi/vins/models.go b/pkg/cloudapi/vins/models.go index 8344625..6bae94c 100644 --- a/pkg/cloudapi/vins/models.go +++ b/pkg/cloudapi/vins/models.go @@ -252,6 +252,9 @@ type ItemVNFInterface struct { // Default GW DefGW string `json:"defGw"` + // Enabled + Enabled bool `json:"enabled"` + // FLIPGroup ID FLIPGroupID uint64 `json:"flipgroupId"` @@ -378,6 +381,9 @@ type RecordNAT struct { // Pure virtual PureVirtual bool `json:"pureVirtual"` + // Routes + Routes ListRoutes `json:"routes"` + // Status Status string `json:"status"` @@ -443,6 +449,9 @@ type RecordGW struct { // Pure virtual PureVirtual bool `json:"pureVirtual"` + // Routes + Routes ListRoutes `json:"routes"` + // Status Status string `json:"status"` @@ -530,6 +539,9 @@ type RecordDHCP struct { // Pure virtual PureVirtual bool `json:"pureVirtual"` + // Routes + Routes ListRoutes `json:"routes"` + // Status Status string `json:"status"` @@ -567,6 +579,39 @@ type RecordDHCPConfig struct { Reservations ListReservations `json:"reservations"` } +// List of static routes +type ListStaticRoutes struct { + // Data + Data []ItemRoutes `json:"data"` + + // Entry count + EntryCount uint64 `json:"entryCount"` +} + +// List of Routes +type ListRoutes []ItemRoutes + +// Detailed information about Routes +type ItemRoutes struct { + //Compute Id + ComputeIds []uint64 `json:"computeIds"` + + // Destination network + Destination string `json:"destination"` + + //Next hop host, IP address from ViNS ID free IP pool + Gateway string `json:"gateway"` + + // GUID + GUID string `json:"guid"` + + // ID + ID uint64 `json:"id"` + + //Destination network mask in 255.255.255.255 format + Netmask string `json:"netmask"` +} + // Detailed information about VINS type RecordVINS struct { // Main information about VNF device diff --git a/pkg/cloudapi/vins/staticRouteList.go b/pkg/cloudapi/vins/staticRouteList.go new file mode 100644 index 0000000..47f96e4 --- /dev/null +++ b/pkg/cloudapi/vins/staticRouteList.go @@ -0,0 +1,42 @@ +package vins + +import ( + "context" + "encoding/json" + "net/http" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for static route list +type StaticRouteListRequest struct { + // ViNS ID to show list of static routes + // Required: true + VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"` +} + +// Show list of static routes for ViNS +func (v VINS) StaticRouteList(ctx context.Context, req StaticRouteListRequest) (*ListStaticRoutes, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return nil, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/vins/staticRouteList" + + res, err := v.client.DecortApiCall(ctx, http.MethodPost, url, req) + if err != nil { + return nil, err + } + + list := ListStaticRoutes{} + + err = json.Unmarshal(res, &list) + if err != nil { + return nil, err + } + + return &list, nil +} diff --git a/pkg/cloudapi/vins/static_route_access_grant.go b/pkg/cloudapi/vins/static_route_access_grant.go new file mode 100644 index 0000000..e8cfea8 --- /dev/null +++ b/pkg/cloudapi/vins/static_route_access_grant.go @@ -0,0 +1,48 @@ +package vins + +import ( + "context" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for grant access to static route to Compute/ViNS +type StaticRouteAccessGrantRequest struct { + // ViNS ID to grant access + // Required: true + VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"` + + // Route ID to grant access, can be found in staticRouteList + // Required: true + RouteId uint64 `url:"routeId" json:"routeId" validate:"required"` + + // List of Compute IDs to grant access to this route + // Required: false + ComputeIds []uint64 `url:"computeIds,omitempty" json:"computeIds,omitempty"` +} + +// Grant access to static route to Compute/ViNS +func (v VINS) StaticRouteAccessGrant(ctx context.Context, req StaticRouteAccessGrantRequest) (bool, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return false, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/vins/staticRouteAccessGrant" + + res, err := v.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 +} diff --git a/pkg/cloudapi/vins/static_route_access_revoke.go b/pkg/cloudapi/vins/static_route_access_revoke.go new file mode 100644 index 0000000..2c2f6ea --- /dev/null +++ b/pkg/cloudapi/vins/static_route_access_revoke.go @@ -0,0 +1,48 @@ +package vins + +import ( + "context" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for revoke access to static route to Compute/ViNS +type StaticRouteAccessRevokeRequest struct { + // ViNS ID to revoke access + // Required: true + VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"` + + // Route ID to revoke access, can be found in staticRouteList + // Required: true + RouteId uint64 `url:"routeId" json:"routeId" validate:"required"` + + // List of Compute IDs to revoke access to this route + // Required: false + ComputeIds []uint64 `url:"computeIds,omitempty" json:"computeIds,omitempty"` +} + +// Revoke access to static route to Compute/ViNS +func (v VINS) StaticRouteAccessRevoke(ctx context.Context, req StaticRouteAccessRevokeRequest) (bool, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return false, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/vins/staticRouteAccessRevoke" + + res, err := v.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 +} diff --git a/pkg/cloudapi/vins/static_route_add.go b/pkg/cloudapi/vins/static_route_add.go new file mode 100644 index 0000000..1776e2d --- /dev/null +++ b/pkg/cloudapi/vins/static_route_add.go @@ -0,0 +1,56 @@ +package vins + +import ( + "context" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for add static route +type StaticRouteAddRequest struct { + // VINS ID + // Required: true + VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"` + + // Destination network + // Required: true + Destination string `url:"destination" json:"destination" validate:"required"` + + // Destination network mask in 255.255.255.255 format + // Required: true + Netmask string `url:"netmask" json:"netmask" validate:"required"` + + // Next hop host, IP address from ViNS ID free IP pool + // Required: true + Gateway string `url:"gateway" json:"gateway" validate:"required"` + + // List of Compute IDs which have access to this route + // Required: false + ComputeIds []uint64 `url:"computeIds,omitempty" json:"computeIds,omitempty"` +} + +// StaticRouteAdd add new static route to ViNS +func (v VINS) StaticRouteAdd(ctx context.Context, req StaticRouteAddRequest) (bool, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return false, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/vins/staticRouteAdd" + + res, err := v.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 +} diff --git a/pkg/cloudapi/vins/static_route_del.go b/pkg/cloudapi/vins/static_route_del.go new file mode 100644 index 0000000..6674e8d --- /dev/null +++ b/pkg/cloudapi/vins/static_route_del.go @@ -0,0 +1,44 @@ +package vins + +import ( + "context" + "net/http" + "strconv" + + "repository.basistech.ru/BASIS/decort-golang-sdk/internal/validators" +) + +// Request struct for remove static route from ViNS +type StaticRouteDelRequest struct { + // ViNS ID to remove static route from + // Required: true + VINSID uint64 `url:"vinsId" json:"vinsId" validate:"required"` + + // Route ID to remove, can be found in staticRouteList + // Required: true + RouteId uint64 `url:"routeId" json:"routeId" validate:"required"` +} + +// Remove static route from ViNS +func (v VINS) StaticRouteDel(ctx context.Context, req StaticRouteDelRequest) (bool, error) { + err := validators.ValidateRequest(req) + if err != nil { + for _, validationError := range validators.GetErrors(err) { + return false, validators.ValidationError(validationError) + } + } + + url := "/cloudapi/vins/staticRouteDel" + + res, err := v.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 +}