Files
golib/aws/configCustom/models.go
Nicolas JUHEL ae0a6b62c9 Package HTTP Client:
- Add DNS Mapper to force destination for a fqdn source
- Allow wildcard and multi wildcard for fqdn source
- DNS Mapper create Transport, Dialer & http client
- DNS Mapper allow a config input to customize timeout, limit and TLS config
- DNS Mapper use a gloabl transport connection poller
- DNS Mapper implement DialContext & Dial method for transport
- DNS Mapper use cache to accelerate process
- DNS Mapper cache is only dnsmapper, not DNS cache
- Replace old helper for http client with DNSMapper
- Add default DNSMapper into the main lib of http client
- Allow to overide the default DNS Mapper with a new one
- Add ticker to force clean idle connection every given duration
- "Compatible" with old config, as the default config will be used instead of old client build
- Clean code and fix minor bugs
- Add config component to allow use a global config
- Config Component httpcli can overide default httpcli dns mapper when updated

Package Certificates
- Add function type to impose function that return a slice of rootCA string
- update config/component/tls by replacing mutex with atomic
- optimize some code

Package Config
- expand errors code index to add component httpcli

Package Config/component:
- database: add new validation, that config key existing into viper
- head: add new validation, that config key existing into viper
- http: add new validation, that config key existing into viper
- ldap: add new validation, that config key existing into viper
- log: add new validation, that config key existing into viper
- mail: add new validation, that config key existing into viper
- smtp: add new validation, that config key existing into viper

Package AWS:
- update package following update of httpcli
- use interface for http cli that implement the Do function
- update following the config/component/aws
- rework config/component/aws to use atomic instead of mutex
- update test unit following change

Package Request:
- update following http client update
- use interface of HTTP Client that implement DO function, instead of http client struct pointer
- update config & code following
- apply same modification into config/component/request
- update config/component/request by replacing mutex to atomic

Package Server
- add function Uptime to model to expose the duration since last start

Package Semaphore
- apply change name of constant following bump of lib associated

Package Crypt
- fix bug into reader to remove suffix of EOF if prevent

Package Errors:
- expand index module to add DNS Mapper client

Package HTTP Server:
- update monitor to apply changes

Package Socket:
- add additional check if reading error: if buffer has data, send it to handler before break run

Other:
- bump dependencies
2024-02-16 15:42:13 +01:00

318 lines
7.8 KiB
Go

/*
* MIT License
*
* Copyright (c) 2020 Nicolas JUHEL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package configCustom
import (
"context"
"fmt"
"net"
"net/url"
"strings"
sdkaws "github.com/aws/aws-sdk-go-v2/aws"
libval "github.com/go-playground/validator/v10"
libhtc "github.com/nabbar/golib/httpcli"
libreq "github.com/nabbar/golib/request"
)
type Model struct {
Region string `mapstructure:"region" json:"region" yaml:"region" toml:"region" validate:"required,hostname"`
Endpoint string `mapstructure:"endpoint" json:"endpoint" yaml:"endpoint" toml:"endpoint" validate:"url"`
AccessKey string `mapstructure:"accesskey" json:"accesskey" yaml:"accesskey" toml:"accesskey" validate:"omitempty,printascii"`
SecretKey string `mapstructure:"secretkey" json:"secretkey" yaml:"secretkey" toml:"secretkey" validate:"omitempty,printascii"`
Bucket string `mapstructure:"bucket" json:"bucket" yaml:"bucket" toml:"bucket" validate:"omitempty,hostname"`
}
type ModelStatus struct {
Config Model `json:"config" yaml:"config" toml:"config" mapstructure:"config" validate:"required"`
Monitor libreq.OptionsHealth `json:"health" yaml:"health" toml:"health" mapstructure:"health" validate:""`
}
type awsModel struct {
Model
retryer func() sdkaws.Retryer
endpoint *url.URL
mapRegion map[string]*url.URL
}
func (c *awsModel) Validate() error {
err := ErrorConfigValidator.Error(nil)
if er := libval.New().Struct(c); er != nil {
if e, ok := er.(*libval.InvalidValidationError); ok {
err.Add(e)
}
for _, e := range er.(libval.ValidationErrors) {
//nolint goerr113
err.Add(fmt.Errorf("config field '%s' is not validated by constraint '%s'", e.StructNamespace(), e.ActualTag()))
}
}
if c.Endpoint != "" && c.endpoint == nil {
var e error
if c.endpoint, e = url.Parse(c.Endpoint); e != nil {
err.Add(e)
} else if er := c.RegisterRegionAws(c.endpoint); er != nil {
err.Add(er)
}
} else if !err.HasParent() && c.endpoint != nil && c.Endpoint == "" {
c.Endpoint = c.endpoint.String()
}
if !err.HasParent() && c.endpoint != nil && c.Region != "" {
if e := c.RegisterRegionEndpoint("", c.endpoint); e != nil {
err.Add(e)
}
}
if !err.HasParent() {
err = nil
}
return err
}
func (c *awsModel) GetAccessKey() string {
return c.AccessKey
}
func (c *awsModel) GetSecretKey() string {
return c.SecretKey
}
func (c *awsModel) SetCredentials(accessKey, secretKey string) {
c.AccessKey = accessKey
c.SecretKey = secretKey
}
func (c *awsModel) ResetRegionEndpoint() {
c.mapRegion = make(map[string]*url.URL)
}
func (c *awsModel) RegisterRegionEndpoint(region string, endpoint *url.URL) error {
if endpoint == nil && c.endpoint != nil {
endpoint = c.endpoint
} else if endpoint == nil && c.Endpoint != "" {
var err error
if endpoint, err = url.Parse(c.Endpoint); err != nil {
return ErrorEndpointInvalid.Error(err)
}
}
if endpoint == nil {
return ErrorEndpointInvalid.Error(nil)
}
if region == "" && c.Region != "" {
region = c.Region
}
val := libval.New()
if err := val.Var(endpoint, "url,required"); err != nil {
return ErrorEndpointInvalid.Error(err)
} else if err := val.Var(region, "printascii,required"); err != nil {
return ErrorRegionInvalid.Error(err)
}
if c.mapRegion == nil {
c.mapRegion = make(map[string]*url.URL)
}
c.mapRegion[region] = endpoint
return nil
}
func (c *awsModel) RegisterRegionAws(endpoint *url.URL) error {
if endpoint == nil && c.endpoint != nil {
endpoint = c.endpoint
} else if endpoint == nil && c.Endpoint != "" {
var err error
if endpoint, err = url.Parse(c.Endpoint); err != nil {
return ErrorEndpointInvalid.Error(err)
}
}
if endpoint == nil {
return ErrorEndpointInvalid.Error(nil)
}
val := libval.New()
if err := val.Var(endpoint, "url,required"); err != nil {
return ErrorEndpointInvalid.Error(err)
}
if c.Region == "" {
c.SetRegion("us-east-1")
}
if c.mapRegion == nil {
c.mapRegion = make(map[string]*url.URL)
}
for _, r := range []string{
"af-south-1",
"ap-east-1",
"ap-northeast-1",
"ap-northeast-2",
"ap-northeast-3",
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"ca-central-1",
"cn-north-1",
"cn-northwest-1",
"eu-central-1",
"eu-north-1",
"eu-south-1",
"eu-west-1",
"eu-west-2",
"eu-west-3",
"me-south-1",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-gov-east-1",
"us-gov-west-1",
"us-west-1",
"us-west-2",
} {
c.mapRegion[r] = endpoint
}
return nil
}
func (c *awsModel) SetRegion(region string) {
c.Region = region
}
func (c *awsModel) GetRegion() string {
return c.Region
}
func (c *awsModel) SetEndpoint(endpoint *url.URL) {
c.endpoint = endpoint
c.Endpoint = strings.TrimSuffix(c.endpoint.String(), "/")
}
func (c *awsModel) GetEndpoint() *url.URL {
return c.endpoint
}
func (c *awsModel) ResolveEndpoint(service, region string) (sdkaws.Endpoint, error) {
return c.ResolveEndpointWithOptions(service, region)
}
func (c *awsModel) ResolveEndpointWithOptions(service, region string, options ...interface{}) (sdkaws.Endpoint, error) {
if e, ok := c.mapRegion[region]; ok {
return sdkaws.Endpoint{
URL: strings.TrimSuffix(e.String(), "/"),
SigningRegion: region,
SigningName: service,
}, nil
}
if c.Endpoint != "" {
return sdkaws.Endpoint{
URL: strings.TrimSuffix(c.Endpoint, "/"),
SigningRegion: region,
SigningName: service,
}, nil
}
return sdkaws.Endpoint{}, ErrorEndpointInvalid.Error(nil)
}
func (c *awsModel) GetDisableHTTPS() bool {
return false
}
func (c *awsModel) GetResolvedRegion() string {
return c.GetRegion()
}
func (c *awsModel) IsHTTPs() bool {
return strings.HasSuffix(strings.ToLower(c.endpoint.Scheme), "s")
}
func (c *awsModel) SetRetryer(retryer func() sdkaws.Retryer) {
c.retryer = retryer
}
func (c *awsModel) Check(ctx context.Context) error {
var (
cfg *sdkaws.Config
con net.Conn
err error
e error
)
if cfg, e = c.GetConfig(ctx, nil); e != nil {
return e
}
if ctx == nil {
ctx = context.Background()
}
if _, err = cfg.EndpointResolverWithOptions.ResolveEndpoint("s3", c.GetRegion()); err != nil {
return ErrorEndpointInvalid.Error(err)
}
if _, err = cfg.Credentials.Retrieve(ctx); err != nil {
return ErrorCredentialsInvalid.Error(err)
}
d := net.Dialer{
Timeout: libhtc.ClientTimeout5Sec,
KeepAlive: libhtc.ClientTimeout5Sec,
}
if c.endpoint.Port() == "" && c.endpoint.Scheme == "http" {
con, err = d.DialContext(ctx, "tcp", c.endpoint.Hostname()+":80")
} else if c.endpoint.Port() == "" && c.endpoint.Scheme == "https" {
con, err = d.DialContext(ctx, "tcp", c.endpoint.Hostname()+":443")
} else {
con, err = d.DialContext(ctx, "tcp", c.endpoint.Host)
}
defer func() {
if con != nil {
_ = con.Close()
}
}()
if err != nil {
return ErrorEndpointInvalid.Error(err)
}
return nil
}