@ -4,26 +4,25 @@ import (
"bytes"
"bytes"
"context"
"context"
"crypto/tls"
"crypto/tls"
"e ncoding/json "
"e rrors "
"fmt"
"fmt"
"io"
"io"
"mime/multipart"
"mime/multipart"
"net/http"
"net/http"
"reflect"
"strconv"
"strconv"
"strings"
"strings"
"sync"
"sync"
"time"
"time"
"github.com/google/go-querystring/query"
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
"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/pkg/cloudapi"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi"
k8s_ca "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/k8s"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker"
k8s_cb "repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudbroker/k8s"
"github.com/google/go-querystring/query"
"repository.basistech.ru/BASIS/decort-golang-sdk/config"
)
)
// DecortClient is HTTP-client for platform
// HTTP-client for platform
type DecortClient struct {
type DecortClient struct {
decortURL string
decortURL string
client * http . Client
client * http . Client
@ -54,7 +53,7 @@ func New(cfg config.Config) *DecortClient {
} ,
} ,
} ,
} ,
} ,
} ,
cfg : trimConfig ( & cfg ) ,
cfg : cfg ,
expiryTime : expiryTime ,
expiryTime : expiryTime ,
mutex : & sync . Mutex { } ,
mutex : & sync . Mutex { } ,
}
}
@ -72,77 +71,321 @@ func (dc *DecortClient) CloudBroker() *cloudbroker.CloudBroker {
// DecortApiCall method for sending requests to the platform
// DecortApiCall method for sending requests to the platform
func ( dc * DecortClient ) DecortApiCall ( ctx context . Context , method , url string , params interface { } ) ( [ ] byte , error ) {
func ( dc * DecortClient ) DecortApiCall ( ctx context . Context , method , url string , params interface { } ) ( [ ] byte , error ) {
k8sCaCreateReq , okCa := params . ( k8s_ca . CreateRequest )
k8sCbCreateReq , okCb := params . ( k8s_cb . CreateRequest )
if okCa {
reqBody := & bytes . Buffer { }
writer := multipart . NewWriter ( reqBody )
if k8sCaCreateReq . OidcCertificate != "" {
part , _ := writer . CreateFormFile ( "oidcCertificate" , "ca.crt" )
_ , _ = io . Copy ( part , strings . NewReader ( k8sCaCreateReq . OidcCertificate ) )
}
var body * bytes . Buffer
_ = writer . WriteField ( "name" , k8sCaCreateReq . Name )
var ctype string
_ = writer . WriteField ( "rgId" , strconv . FormatUint ( k8sCaCreateReq . RGID , 10 ) )
_ = writer . WriteField ( "k8ciId" , strconv . FormatUint ( k8sCaCreateReq . K8SCIID , 10 ) )
_ = writer . WriteField ( "workerGroupName" , k8sCaCreateReq . WorkerGroupName )
_ = writer . WriteField ( "networkPlugin" , k8sCaCreateReq . NetworkPlugin )
byteSlice , ok := params . ( [ ] byte )
if k8sCaCreateReq . MasterSEPID != 0 {
if ok {
_ = writer . WriteField ( "masterSepId" , strconv . FormatUint ( k8sCaCreateReq . MasterSEPID , 10 ) )
body = bytes . NewBuffer ( byteSlice )
}
// ctype = "application/x-iso9660-image"
if k8sCaCreateReq . MasterSEPPool != "" {
ctype = "application/octet-stream"
_ = writer . WriteField ( "masterSepPool" , k8sCaCreateReq . MasterSEPPool )
} else {
}
values , err := query . Values ( params )
if k8sCaCreateReq . WorkerSEPID != 0 {
_ = writer . WriteField ( "workerSepId" , strconv . FormatUint ( k8sCaCreateReq . WorkerSEPID , 10 ) )
}
if k8sCaCreateReq . WorkerSEPPool != "" {
_ = writer . WriteField ( "workerSepPool" , k8sCaCreateReq . WorkerSEPPool )
}
if k8sCaCreateReq . Labels != nil {
for _ , v := range k8sCaCreateReq . Labels {
_ = writer . WriteField ( "labels" , v )
}
}
if k8sCaCreateReq . Taints != nil {
for _ , v := range k8sCaCreateReq . Taints {
_ = writer . WriteField ( "taints" , v )
}
}
if k8sCaCreateReq . Annotations != nil {
for _ , v := range k8sCaCreateReq . Annotations {
_ = writer . WriteField ( "annotations" , v )
}
}
if k8sCaCreateReq . MasterCPU != 0 {
_ = writer . WriteField ( "masterCpu" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . MasterCPU ) , 10 ) )
}
if k8sCaCreateReq . MasterNum != 0 {
_ = writer . WriteField ( "masterNum" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . MasterNum ) , 10 ) )
}
if k8sCaCreateReq . MasterRAM != 0 {
_ = writer . WriteField ( "masterRam" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . MasterRAM ) , 10 ) )
}
if k8sCaCreateReq . MasterDisk != 0 {
_ = writer . WriteField ( "masterDisk" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . MasterDisk ) , 10 ) )
}
if k8sCaCreateReq . WorkerCPU != 0 {
_ = writer . WriteField ( "workerCpu" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . WorkerCPU ) , 10 ) )
}
if k8sCaCreateReq . WorkerNum != 0 {
_ = writer . WriteField ( "workerNum" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . WorkerNum ) , 10 ) )
}
if k8sCaCreateReq . WorkerRAM != 0 {
_ = writer . WriteField ( "workerRam" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . WorkerRAM ) , 10 ) )
}
if k8sCaCreateReq . WorkerDisk != 0 {
_ = writer . WriteField ( "workerDisk" , strconv . FormatUint ( uint64 ( k8sCaCreateReq . WorkerDisk ) , 10 ) )
}
if k8sCaCreateReq . ExtNetID != 0 {
_ = writer . WriteField ( "extnetId" , strconv . FormatUint ( k8sCaCreateReq . ExtNetID , 10 ) )
}
if k8sCaCreateReq . VinsId != 0 {
_ = writer . WriteField ( "vinsId" , strconv . FormatUint ( k8sCaCreateReq . VinsId , 10 ) )
}
if ! k8sCaCreateReq . WithLB {
_ = writer . WriteField ( "withLB" , strconv . FormatBool ( k8sCaCreateReq . WithLB ) )
}
_ = writer . WriteField ( "highlyAvailableLB" , strconv . FormatBool ( k8sCaCreateReq . HighlyAvailable ) )
if k8sCaCreateReq . AdditionalSANs != nil {
for _ , v := range k8sCaCreateReq . AdditionalSANs {
_ = writer . WriteField ( "additionalSANs" , v )
}
}
if k8sCaCreateReq . InitConfiguration != "" {
_ = writer . WriteField ( "initConfiguration" , k8sCaCreateReq . InitConfiguration )
}
if k8sCaCreateReq . ClusterConfiguration != "" {
_ = writer . WriteField ( "clusterConfiguration" , k8sCaCreateReq . ClusterConfiguration )
}
if k8sCaCreateReq . KubeletConfiguration != "" {
_ = writer . WriteField ( "kubeletConfiguration" , k8sCaCreateReq . KubeletConfiguration )
}
if k8sCaCreateReq . KubeProxyConfiguration != "" {
_ = writer . WriteField ( "kubeProxyConfiguration" , k8sCaCreateReq . KubeProxyConfiguration )
}
if k8sCaCreateReq . JoinConfiguration != "" {
_ = writer . WriteField ( "joinConfiguration" , k8sCaCreateReq . JoinConfiguration )
}
if k8sCaCreateReq . Description != "" {
_ = writer . WriteField ( "desc" , k8sCaCreateReq . Description )
}
if k8sCaCreateReq . UserData != "" {
_ = writer . WriteField ( "userData" , k8sCaCreateReq . UserData )
}
_ = writer . WriteField ( "extnetOnly" , strconv . FormatBool ( k8sCaCreateReq . ExtNetOnly ) )
_ = writer . FormDataContentType ( )
ct := writer . FormDataContentType ( )
writer . Close ( )
req , err := http . NewRequestWithContext ( ctx , method , dc . decortURL + "/restmachine" + url , reqBody )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
body = bytes . NewBufferString ( values . Encode ( ) )
if err = dc . getToken ( ctx ) ; err != nil {
return nil , err
}
resp , err := dc . domp ( req , ct )
if err != nil {
return nil , err
}
}
defer resp . Body . Close ( )
req , err := http . NewRequestWithContext ( ctx , method , dc . decortURL + constants . RESTMACHINE + url , body )
respBytes , err := io . ReadAll ( resp . B ody)
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
// get token
if resp . StatusCode != 200 {
return nil , errors . New ( string ( respBytes ) )
}
return respBytes , nil
} else if okCb {
reqBody := & bytes . Buffer { }
writer := multipart . NewWriter ( reqBody )
if k8sCbCreateReq . OidcCertificate != "" {
part , _ := writer . CreateFormFile ( "oidcCertificate" , "ca.crt" )
_ , _ = io . Copy ( part , strings . NewReader ( k8sCbCreateReq . OidcCertificate ) )
}
_ = writer . WriteField ( "name" , k8sCbCreateReq . Name )
_ = writer . WriteField ( "rgId" , strconv . FormatUint ( k8sCbCreateReq . RGID , 10 ) )
_ = writer . WriteField ( "k8ciId" , strconv . FormatUint ( k8sCbCreateReq . K8CIID , 10 ) )
_ = writer . WriteField ( "workerGroupName" , k8sCbCreateReq . WorkerGroupName )
_ = writer . WriteField ( "networkPlugin" , k8sCbCreateReq . NetworkPlugin )
if k8sCbCreateReq . MasterSEPID != 0 {
_ = writer . WriteField ( "masterSepId" , strconv . FormatUint ( k8sCbCreateReq . MasterSEPID , 10 ) )
}
if k8sCbCreateReq . MasterSEPPool != "" {
_ = writer . WriteField ( "masterSepPool" , k8sCbCreateReq . MasterSEPPool )
}
if k8sCbCreateReq . WorkerSEPID != 0 {
_ = writer . WriteField ( "workerSepId" , strconv . FormatUint ( k8sCbCreateReq . WorkerSEPID , 10 ) )
}
if k8sCbCreateReq . WorkerSEPPool != "" {
_ = writer . WriteField ( "workerSepPool" , k8sCbCreateReq . WorkerSEPPool )
}
if k8sCbCreateReq . Labels != nil {
for _ , v := range k8sCbCreateReq . Labels {
_ = writer . WriteField ( "labels" , v )
}
}
if k8sCbCreateReq . Taints != nil {
for _ , v := range k8sCbCreateReq . Taints {
_ = writer . WriteField ( "taints" , v )
}
}
if k8sCbCreateReq . Annotations != nil {
for _ , v := range k8sCbCreateReq . Annotations {
_ = writer . WriteField ( "annotations" , v )
}
}
if k8sCbCreateReq . MasterCPU != 0 {
_ = writer . WriteField ( "masterCpu" , strconv . FormatUint ( k8sCbCreateReq . MasterCPU , 10 ) )
}
if k8sCbCreateReq . MasterNum != 0 {
_ = writer . WriteField ( "masterNum" , strconv . FormatUint ( k8sCbCreateReq . MasterNum , 10 ) )
}
if k8sCbCreateReq . MasterRAM != 0 {
_ = writer . WriteField ( "masterRam" , strconv . FormatUint ( k8sCbCreateReq . MasterRAM , 10 ) )
}
if k8sCbCreateReq . MasterDisk != 0 {
_ = writer . WriteField ( "masterDisk" , strconv . FormatUint ( k8sCbCreateReq . MasterDisk , 10 ) )
}
if k8sCbCreateReq . WorkerCPU != 0 {
_ = writer . WriteField ( "workerCpu" , strconv . FormatUint ( k8sCbCreateReq . WorkerCPU , 10 ) )
}
if k8sCbCreateReq . WorkerNum != 0 {
_ = writer . WriteField ( "workerNum" , strconv . FormatUint ( k8sCbCreateReq . WorkerNum , 10 ) )
}
if k8sCbCreateReq . WorkerRAM != 0 {
_ = writer . WriteField ( "workerRam" , strconv . FormatUint ( k8sCbCreateReq . WorkerRAM , 10 ) )
}
if k8sCbCreateReq . WorkerDisk != 0 {
_ = writer . WriteField ( "workerDisk" , strconv . FormatUint ( k8sCbCreateReq . WorkerDisk , 10 ) )
}
if k8sCbCreateReq . ExtNetID != 0 {
_ = writer . WriteField ( "extnetId" , strconv . FormatUint ( k8sCbCreateReq . ExtNetID , 10 ) )
}
if k8sCbCreateReq . VinsId != 0 {
_ = writer . WriteField ( "vinsId" , strconv . FormatUint ( k8sCbCreateReq . VinsId , 10 ) )
}
if ! k8sCbCreateReq . WithLB {
_ = writer . WriteField ( "withLB" , strconv . FormatBool ( k8sCbCreateReq . WithLB ) )
}
_ = writer . WriteField ( "highlyAvailableLB" , strconv . FormatBool ( k8sCbCreateReq . HighlyAvailable ) )
if k8sCbCreateReq . AdditionalSANs != nil {
for _ , v := range k8sCbCreateReq . AdditionalSANs {
_ = writer . WriteField ( "additionalSANs" , v )
}
}
if k8sCbCreateReq . InitConfiguration != "" {
_ = writer . WriteField ( "initConfiguration" , k8sCbCreateReq . InitConfiguration )
}
if k8sCbCreateReq . ClusterConfiguration != "" {
_ = writer . WriteField ( "clusterConfiguration" , k8sCbCreateReq . ClusterConfiguration )
}
if k8sCbCreateReq . KubeletConfiguration != "" {
_ = writer . WriteField ( "kubeletConfiguration" , k8sCbCreateReq . KubeletConfiguration )
}
if k8sCbCreateReq . KubeProxyConfiguration != "" {
_ = writer . WriteField ( "kubeProxyConfiguration" , k8sCbCreateReq . KubeProxyConfiguration )
}
if k8sCbCreateReq . JoinConfiguration != "" {
_ = writer . WriteField ( "joinConfiguration" , k8sCbCreateReq . JoinConfiguration )
}
if k8sCbCreateReq . Description != "" {
_ = writer . WriteField ( "desc" , k8sCbCreateReq . Description )
}
if k8sCbCreateReq . UserData != "" {
_ = writer . WriteField ( "userData" , k8sCbCreateReq . UserData )
}
_ = writer . WriteField ( "extnetOnly" , strconv . FormatBool ( k8sCbCreateReq . ExtNetOnly ) )
_ = writer . FormDataContentType ( )
ct := writer . FormDataContentType ( )
writer . Close ( )
req , err := http . NewRequestWithContext ( ctx , method , dc . decortURL + "/restmachine" + url , reqBody )
if err != nil {
return nil , err
}
if err = dc . getToken ( ctx ) ; err != nil {
if err = dc . getToken ( ctx ) ; err != nil {
return nil , err
return nil , err
}
}
// perform request
respBytes , err := dc . do ( req , ctype )
resp , err := dc . domp ( req , ct )
if err != nil {
return nil , err
}
defer resp . Body . Close ( )
respBytes , err := io . ReadAll ( resp . Body )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
return respBytes , err
if resp . StatusCode != 200 {
}
return nil , errors . New ( string ( respBytes ) )
}
// DecortApiCallMP method for sending requests to the platform
return respBytes , nil
func ( dc * DecortClient ) DecortApiCallMP ( ctx context . Context , method , url string , params interface { } ) ( [ ] byte , error ) {
}
body , ctype , err := multiPartReq ( params )
values , err := query . Values ( params )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
req , err := http . NewRequestWithContext ( ctx , method , dc . decortURL + constants . RESTMACHINE + url , body )
body := strings . NewReader ( values . Encode ( ) )
req , err := http . NewRequestWithContext ( ctx , method , dc . decortURL + "/restmachine" + url , body )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
// get token
if err = dc . getToken ( ctx ) ; err != nil {
if err = dc . getToken ( ctx ) ; err != nil {
return nil , err
return nil , err
}
}
// perform request
resp , err := dc . do ( req )
respBytes , err := dc . do ( req , ctype )
if err != nil {
if err != nil {
return nil , err
return nil , err
}
}
defer resp . Body . Close ( )
return respBytes , err
respBytes , err := io . ReadAll ( resp . Body )
if err != nil {
return nil , err
}
if resp . StatusCode != 200 {
return nil , errors . New ( string ( respBytes ) )
}
return respBytes , nil
}
}
func ( dc * DecortClient ) getToken ( ctx context . Context ) error {
func ( dc * DecortClient ) getToken ( ctx context . Context ) error {
dc . mutex . Lock ( )
dc . mutex . Lock ( )
defer dc . mutex . Unlock ( )
defer dc . mutex . Unlock ( )
// new token is not needed
if dc . cfg . Token == "" || time . Now ( ) . After ( dc . expiryTime ) {
if dc . cfg . Token != "" && ! time . Now ( ) . After ( dc . expiryTime ) {
return nil
}
// set up request headers and body
body := fmt . Sprintf ( "grant_type=client_credentials&client_id=%s&client_secret=%s&response_type=id_token" , dc . cfg . AppID , dc . cfg . AppSecret )
body := fmt . Sprintf ( "grant_type=client_credentials&client_id=%s&client_secret=%s&response_type=id_token" , dc . cfg . AppID , dc . cfg . AppSecret )
bodyReader := strings . NewReader ( body )
bodyReader := strings . NewReader ( body )
@ -151,227 +394,77 @@ func (dc *DecortClient) getToken(ctx context.Context) error {
req , _ := http . NewRequestWithContext ( ctx , "POST" , dc . cfg . SSOURL + "/v1/oauth/access_token" , bodyReader )
req , _ := http . NewRequestWithContext ( ctx , "POST" , dc . cfg . SSOURL + "/v1/oauth/access_token" , bodyReader )
req . Header . Add ( "Content-Type" , "application/x-www-form-urlencoded" )
req . Header . Add ( "Content-Type" , "application/x-www-form-urlencoded" )
// request token
resp , err := dc . client . Do ( req )
resp , err := dc . client . Do ( req )
if err != nil || resp == nil {
return fmt . Errorf ( "cannot get token: %w" , err )
}
defer resp . Body . Close ( )
var tokenBytes [ ] byte
tokenBytes , err = io . ReadAll ( resp . Body )
if err != nil {
if err != nil {
return fmt . Errorf ( "cannot get token: %w" , err )
return fmt . Errorf ( "cannot get token: %w" , err )
}
}
tokenBytes , _ := io . ReadAll ( resp . Body )
resp . Body . Close ( )
if resp . StatusCode != 200 {
if resp . StatusCode != 200 {
return fmt . Errorf ( "cannot get token: %s" , tokenBytes )
return fmt . Errorf ( "cannot get token: %s" , tokenBytes )
}
}
// save token in config
token := string ( tokenBytes )
token := string ( tokenBytes )
dc . cfg . Token = token
dc . cfg . Token = token
dc . expiryTime = time . Now ( ) . AddDate ( 0 , 0 , 1 )
dc . expiryTime = time . Now ( ) . AddDate ( 0 , 0 , 1 )
}
return nil
return nil
}
}
// do method performs request and returns response as an array of bytes and nil error in case of response status code 200.
func ( dc * DecortClient ) do ( req * http . Request ) ( * http . Response , error ) {
// In any other cases do returns nil response and error.
// Retries are implemented in case of connection reset errors.
func ( dc * DecortClient ) do ( req * http . Request , ctype string ) ( [ ] byte , error ) {
// set up request headers and body
req . Header . Add ( "Content-Type" , "application/x-www-form-urlencoded" )
req . Header . Add ( "Content-Type" , "application/x-www-form-urlencoded" )
if ctype != "" {
req . Header . Set ( "Content-Type" , ctype )
}
req . Header . Add ( "Authorization" , "bearer " + dc . cfg . Token )
req . Header . Add ( "Authorization" , "bearer " + dc . cfg . Token )
req . Header . Set ( "Accept" , "application/json" )
req . Header . Set ( "Accept" , "application/json" )
buf , err := io . ReadAll ( req . Body )
// var resp *http.Response
if err != nil {
// var err error
return nil , err
buf , _ := io . ReadAll ( req . Body )
}
// req = req.Clone(req.Context())
req . Body . Close ( )
// for i := uint64(0); i < dc.cfg.Retries; i++ {
req . Body = io . NopCloser ( bytes . NewBuffer ( buf ) )
req . Body = io . NopCloser ( bytes . NewBuffer ( buf ) )
resp , err := dc . client . Do ( req )
resp , err := dc . client . Do ( req )
if resp != nil {
defer resp . Body . Close ( )
}
// retries logic GOES HERE
// get http response
//var resp *http.Response
//for i := uint64(0); i < dc.cfg.Retries; i++ {
// req := req.Clone(req.Context())
// req.Body = io.NopCloser(bytes.NewBuffer(buf))
//
// if i > 0 {
// time.Sleep(5 * time.Second) // no time sleep for the first request
// }
//
// resp, err = dc.client.Do(req)
//
// // stop retries on success and close response body
// if resp != nil {
// defer resp.Body.Close()
// }
// if err == nil {
// if err == nil {
// break
// }
//
// // retries in case of connection errors with time sleep
// if isConnectionError(err) {
// continue
// }
//
// // return error in case of non-connection error
// return nil, err
//}
// handle http request errors
if err != nil {
return nil , err
}
if resp == nil {
return nil , fmt . Errorf ( "got empty response without error" )
}
// handle successful request
respBytes , _ := io . ReadAll ( resp . Body )
if resp . StatusCode == 200 {
if resp . StatusCode == 200 {
return resp Bytes, nil
return resp , err
}
}
respBytes , _ := io . ReadAll ( resp . Body )
// handle errors with status code other than 200
err = fmt . Errorf ( "%s" , respBytes )
err = fmt . Errorf ( "%s" , respBytes )
resp . Body . Close ( )
// }
// }
return nil , fmt . Errorf ( "could not execute request: %w" , err )
return nil , fmt . Errorf ( "could not execute request: %w" , err )
}
}
// isConnectionError checks if given error falls within specific and associated connection errors
func ( dc * DecortClient ) domp ( req * http . Request , ctype string ) ( * http . Response , error ) {
//func isConnectionError(err error) bool {
req . Header . Add ( "Content-Type" , ctype )
// if strings.Contains(err.Error(), "connection reset by peer") {
req . Header . Add ( "Authorization" , "bearer " + dc . cfg . Token )
// return true
req . Header . Set ( "Accept" , "application/json" )
// }
// if errors.Is(err, io.EOF) {
// return true
// }
//
// return false
//}
// multiPartReq writes the request structure to the request body, and also returns string of the content-type
func multiPartReq ( params interface { } ) ( * bytes . Buffer , string , error ) {
reqBody := & bytes . Buffer { }
writer := multipart . NewWriter ( reqBody )
values := reflect . ValueOf ( params )
types := values . Type ( )
defer writer . Close ( )
for i := 0 ; i < values . NumField ( ) ; i ++ {
if ! values . Field ( i ) . IsValid ( ) {
continue
}
if values . Field ( i ) . IsZero ( ) {
continue
}
if file , ok := constants . FileName [ types . Field ( i ) . Name ] ; ok {
// var resp *http.Response
part , err := writer . CreateFormFile ( trimString ( types . Field ( i ) ) , file )
// var err error
if err != nil {
buf , _ := io . ReadAll ( req . Body )
return & bytes . Buffer { } , "" , err
// req = req.Clone(req.Context())
}
_ , err = io . Copy ( part , strings . NewReader ( valueToString ( values . Field ( i ) . Interface ( ) ) ) )
if err != nil {
return & bytes . Buffer { } , "" , err
}
continue
}
if values . Field ( i ) . Type ( ) . Kind ( ) == reflect . Slice {
// for i := uint64(0); i < dc.cfg.Retries; i++ {
switch slice := values . Field ( i ) . Interface ( ) . ( type ) {
req . Body = io . NopCloser ( bytes . NewBuffer ( buf ) )
case [ ] string :
resp , err := dc . client . Do ( req )
if validators . IsInSlice ( trimString ( types . Field ( i ) ) , constants . K8sValues ) {
code , err := json . Marshal ( slice )
if err != nil {
return & bytes . Buffer { } , "" , err
}
err = writer . WriteField ( trimString ( types . Field ( i ) ) , string ( code ) )
if err != nil {
return & bytes . Buffer { } , "" , err
}
} else {
for _ , val := range slice {
err := writer . WriteField ( trimString ( types . Field ( i ) ) , val )
if err != nil {
return & bytes . Buffer { } , "" , err
}
}
}
case [ ] uint :
for _ , val := range slice {
err := writer . WriteField ( trimString ( types . Field ( i ) ) , strconv . FormatUint ( uint64 ( val ) , 10 ) )
if err != nil {
return & bytes . Buffer { } , "" , err
}
}
case [ ] uint64 :
for _ , val := range slice {
err := writer . WriteField ( trimString ( types . Field ( i ) ) , strconv . FormatUint ( val , 10 ) )
if err != nil {
return & bytes . Buffer { } , "" , err
}
}
case [ ] map [ string ] interface { } :
for _ , val := range slice {
encodeStr , err := json . Marshal ( val )
if err != nil {
return & bytes . Buffer { } , "" , err
}
err = writer . WriteField ( trimString ( types . Field ( i ) ) , string ( encodeStr ) )
if err != nil {
return & bytes . Buffer { } , "" , err
}
}
default :
return & bytes . Buffer { } , "" , fmt . Errorf ( "unsupported slice type:%T" , slice )
}
continue
}
err := writer . WriteField ( trimString ( types . Field ( i ) ) , valueToString ( values . Field ( i ) . Interface ( ) ) )
if err != nil {
return & bytes . Buffer { } , "" , err
}
}
ct := writer . FormDataContentType ( )
return reqBody , ct , nil
}
func valueToString ( a any ) string {
// if err == nil {
switch str := a . ( type ) {
if resp . StatusCode == 200 {
case string :
return resp , err
return str
case uint :
return strconv . FormatUint ( uint64 ( str ) , 10 )
case uint64 :
return strconv . FormatUint ( str , 10 )
case bool :
return strconv . FormatBool ( str )
default :
return ""
}
}
}
respBytes , _ := io . ReadAll ( resp . Body )
err = fmt . Errorf ( "%s" , respBytes )
func trimString ( el reflect . StructField ) string {
resp . Body . Close ( )
return strings . TrimSuffix ( el . Tag . Get ( "url" ) , ",omitempty" )
// }
}
// }
func trimConfig ( cfg * config . Config ) config . Config {
return nil , fmt . Errorf ( "could not execute request: %w" , err )
cfg . SSOURL = strings . TrimSuffix ( cfg . SSOURL , "/" )
cfg . DecortURL = strings . TrimSuffix ( cfg . DecortURL , "/" )
return * cfg
}
}