Skip to content

Commit 612b35a

Browse files
authored
Feat: add support for object storage (#33)
* initial configuration changes for object-storage support * export signer middleware function * add s3 access and secret keys to credentials struct
1 parent 01a1ff9 commit 612b35a

File tree

3 files changed

+85
-11
lines changed

3 files changed

+85
-11
lines changed

shared/configuration.go

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,21 @@
55
package shared
66

77
import (
8+
"bytes"
89
"context"
910
"crypto/tls"
1011
"crypto/x509"
1112
"fmt"
13+
"io"
1214
"net"
1315
"net/http"
1416
"net/url"
1517
"os"
1618
"strings"
1719
"time"
20+
21+
"github.com/aws/aws-sdk-go/aws/credentials"
22+
awsv4 "github.com/aws/aws-sdk-go/aws/signer/v4"
1823
)
1924

2025
var DefaultIonosBasePath = ""
@@ -28,6 +33,8 @@ const (
2833
IonosLogLevelEnvVar = "IONOS_LOG_LEVEL"
2934
IonosFilePathEnvVar = "IONOS_CONFIG_FILE"
3035
IonosCurrentProfileEnvVar = "IONOS_CURRENT_PROFILE"
36+
IonosS3AccessKeyEnvVar = "IONOS_S3_ACCESS_KEY"
37+
IonosS3SecretKeyEnvVar = "IONOS_S3_SECRET_KEY"
3138
DefaultIonosServerUrl = "https://api.ionos.com/"
3239

3340
defaultMaxRetries = 3
@@ -103,6 +110,15 @@ type ServerConfiguration struct {
103110
// ServerConfigurations stores multiple ServerConfiguration items
104111
type ServerConfigurations []ServerConfiguration
105112

113+
// MiddlewareFunction provides way to implement custom middleware in the prepareRequest
114+
type MiddlewareFunction func(*http.Request)
115+
116+
// MiddlewareFunctionWithError provides way to implement custom middleware with errors in the prepareRequest
117+
type MiddlewareFunctionWithError func(*http.Request) error
118+
119+
// ResponseMiddlewareFunction provides way to implement custom middleware with errors after the response is received
120+
type ResponseMiddlewareFunction func(*http.Response, []byte) error
121+
106122
// Configuration stores the configuration of the API client
107123
type Configuration struct {
108124
Host string `json:"host,omitempty"`
@@ -119,6 +135,10 @@ type Configuration struct {
119135
MaxRetries int `json:"maxRetries,omitempty"`
120136
WaitTime time.Duration `json:"waitTime,omitempty"`
121137
MaxWaitTime time.Duration `json:"maxWaitTime,omitempty"`
138+
139+
Middleware MiddlewareFunction `json:"-"`
140+
MiddlewareWithError MiddlewareFunctionWithError `json:"-"`
141+
ResponseMiddleware ResponseMiddlewareFunction `json:"-"`
122142
}
123143

124144
// NewConfiguration returns a new shared.Configuration object
@@ -161,9 +181,11 @@ type ClientOptions struct {
161181

162182
// Credentials are the credentials that will be used for authentication
163183
type Credentials struct {
164-
Username string `yaml:"username"`
165-
Password string `yaml:"password"`
166-
Token string `yaml:"token"`
184+
Username string `yaml:"username"`
185+
Password string `yaml:"password"`
186+
Token string `yaml:"token"`
187+
S3AccessKey string `yaml:"s3AccessKey"`
188+
S3SecretKey string `yaml:"s3SecretKey"`
167189
}
168190

169191
// NewConfigurationFromOptions returns a new shared.Configuration object created from the client options
@@ -217,7 +239,10 @@ func CreateTransport(insecure bool, certificate string) *http.Transport {
217239
}
218240

219241
func NewConfigurationFromEnv() *Configuration {
220-
return NewConfiguration(os.Getenv(IonosUsernameEnvVar), os.Getenv(IonosPasswordEnvVar), os.Getenv(IonosTokenEnvVar), os.Getenv(IonosApiUrlEnvVar))
242+
return NewConfiguration(
243+
os.Getenv(IonosUsernameEnvVar), os.Getenv(IonosPasswordEnvVar), os.Getenv(IonosTokenEnvVar),
244+
os.Getenv(IonosApiUrlEnvVar),
245+
)
221246
}
222247

223248
// AddDefaultHeader adds a new HTTP header to the default header in the request
@@ -253,7 +278,10 @@ func (sc ServerConfigurations) URL(index int, variables map[string]string) (stri
253278
}
254279
}
255280
if !found {
256-
return "", fmt.Errorf("the variable %s in the server URL has invalid value %v. Must be %v", name, value, variable.EnumValues)
281+
return "", fmt.Errorf(
282+
"the variable %s in the server URL has invalid value %v. Must be %v", name, value,
283+
variable.EnumValues,
284+
)
257285
}
258286
serverUrl = strings.Replace(serverUrl, "{"+name+"}", value, -1)
259287
} else {
@@ -305,7 +333,9 @@ func getServerVariables(ctx context.Context) (map[string]string, error) {
305333
if variables, ok := sv.(map[string]string); ok {
306334
return variables, nil
307335
}
308-
return nil, reportError("ctx value of ContextServerVariables has invalid type %T should be map[string]string", sv)
336+
return nil, reportError(
337+
"ctx value of ContextServerVariables has invalid type %T should be map[string]string", sv,
338+
)
309339
}
310340
return nil, nil
311341
}
@@ -314,7 +344,10 @@ func getServerOperationVariables(ctx context.Context, endpoint string) (map[stri
314344
osv := ctx.Value(ContextOperationServerVariables)
315345
if osv != nil {
316346
if operationVariables, ok := osv.(map[string]map[string]string); !ok {
317-
return nil, reportError("ctx value of ContextOperationServerVariables has invalid type %T should be map[string]map[string]string", osv)
347+
return nil, reportError(
348+
"ctx value of ContextOperationServerVariables has invalid type %T should be map[string]map[string]string",
349+
osv,
350+
)
318351
} else {
319352
variables, ok := operationVariables[endpoint]
320353
if ok {
@@ -402,10 +435,12 @@ func OverrideLocationFor(configProvider ConfigProvider, location, endpoint strin
402435
}
403436
}
404437
SdkLogger.Printf("[DEBUG] Adding new server configuration for location %s", location)
405-
configProvider.GetConfig().Servers = append(configProvider.GetConfig().Servers, ServerConfiguration{
406-
URL: endpoint,
407-
Description: EndpointOverridden + location,
408-
})
438+
configProvider.GetConfig().Servers = append(
439+
configProvider.GetConfig().Servers, ServerConfiguration{
440+
URL: endpoint,
441+
Description: EndpointOverridden + location,
442+
},
443+
)
409444
}
410445

411446
func SetSkipTLSVerify(configProvider ConfigProvider, skipTLSVerify bool) {
@@ -425,3 +460,27 @@ func AddCertsToClient(authorityData string) *x509.CertPool {
425460
}
426461
return rootCAs
427462
}
463+
464+
func SignerMiddleware(region, service, accessKey, secretKey string) MiddlewareFunctionWithError {
465+
signer := awsv4.NewSigner(credentials.NewStaticCredentials(accessKey, secretKey, ""))
466+
467+
// Define default values for region and service to maintain backward compatibility
468+
if region == "" {
469+
region = "eu-central-3"
470+
}
471+
if service == "" {
472+
service = "s3"
473+
}
474+
return func(r *http.Request) error {
475+
var reader io.ReadSeeker
476+
if r.Body != nil {
477+
bodyBytes, err := io.ReadAll(r.Body)
478+
if err != nil {
479+
return err
480+
}
481+
reader = bytes.NewReader(bodyBytes)
482+
}
483+
_, err := signer.Sign(r, reader, service, region, time.Now())
484+
return err
485+
}
486+
}

shared/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ module github.com/ionos-cloud/sdk-go-bundle/shared
22

33
go 1.20
44

5+
require (
6+
github.com/aws/aws-sdk-go v1.55.6 // indirect
7+
github.com/jmespath/go-jmespath v0.4.0 // indirect
8+
)
9+
510
require (
611
github.com/stretchr/testify v1.10.0
712
gopkg.in/yaml.v3 v3.0.1

shared/go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk=
2+
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
3+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
5+
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
6+
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
7+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
8+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10+
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
111
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
212
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
313
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

0 commit comments

Comments
 (0)