mirror of
https://github.com/arangodb/kube-arangodb.git
synced 2024-12-14 11:57:37 +00:00
[Feature] Expose HTTP Client Config (#1680)
This commit is contained in:
parent
a0234751d6
commit
70cdbff501
11 changed files with 296 additions and 112 deletions
|
@ -4,6 +4,7 @@
|
||||||
- (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries
|
- (Maintenance) Go 1.22.4 & Kubernetes 1.29.6 libraries
|
||||||
- (Feature) Fix CRD Schema types
|
- (Feature) Fix CRD Schema types
|
||||||
- (Bugfix) Adjust Prometheus Monitor labels
|
- (Bugfix) Adjust Prometheus Monitor labels
|
||||||
|
- (Feature) Expose HTTP Client Config
|
||||||
|
|
||||||
## [1.2.41](https://github.com/arangodb/kube-arangodb/tree/1.2.41) (2024-05-24)
|
## [1.2.41](https://github.com/arangodb/kube-arangodb/tree/1.2.41) (2024-05-24)
|
||||||
- (Maintenance) Bump Prometheus API Version
|
- (Maintenance) Bump Prometheus API Version
|
||||||
|
|
|
@ -166,6 +166,14 @@ Flags:
|
||||||
--deployment.feature.upgrade-version-check Enable initContainer with pre version check - Required ArangoDB 3.8.0 or higher (default true)
|
--deployment.feature.upgrade-version-check Enable initContainer with pre version check - Required ArangoDB 3.8.0 or higher (default true)
|
||||||
--deployment.feature.upgrade-version-check-v2 Enable initContainer with pre version check based by Operator - Required ArangoDB 3.8.0 or higher
|
--deployment.feature.upgrade-version-check-v2 Enable initContainer with pre version check based by Operator - Required ArangoDB 3.8.0 or higher
|
||||||
--features-config-map-name string Name of the Feature Map ConfigMap (default "arangodb-operator-feature-config-map")
|
--features-config-map-name string Name of the Feature Map ConfigMap (default "arangodb-operator-feature-config-map")
|
||||||
|
--http1.keep-alive If false, disables HTTP keep-alives and will only use the connection to the server for a single HTTP request (default true)
|
||||||
|
--http1.transport.dial-timeout duration Maximum amount of time a dial will wait for a connect to complete (default 30s)
|
||||||
|
--http1.transport.idle-conn-timeout duration Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit (default 1m30s)
|
||||||
|
--http1.transport.idle-conn-timeout-short duration Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit (default 100ms)
|
||||||
|
--http1.transport.keep-alive-timeout duration Interval between keep-alive probes for an active network connection (default 1m30s)
|
||||||
|
--http1.transport.keep-alive-timeout-short duration Interval between keep-alive probes for an active network connection (default 100ms)
|
||||||
|
--http1.transport.max-idle-conns int Maximum number of idle (keep-alive) connections across all hosts. Zero means no limit (default 100)
|
||||||
|
--http1.transport.tls-handshake-timeout duration Maximum amount of time to wait for a TLS handshake. Zero means no timeout (default 10s)
|
||||||
--image.discovery.status Discover Operator Image from Pod Status by default. When disabled Pod Spec is used. (default true)
|
--image.discovery.status Discover Operator Image from Pod Status by default. When disabled Pod Spec is used. (default true)
|
||||||
--image.discovery.timeout duration Timeout for image discovery process (default 1m0s)
|
--image.discovery.timeout duration Timeout for image discovery process (default 1m0s)
|
||||||
--internal.scaling-integration Enable Scaling Integration
|
--internal.scaling-integration Enable Scaling Integration
|
||||||
|
|
|
@ -262,6 +262,9 @@ func init() {
|
||||||
if err := reconcile.ActionsConfigGlobal.Init(&cmdMain); err != nil {
|
if err := reconcile.ActionsConfigGlobal.Init(&cmdMain); err != nil {
|
||||||
panic(err.Error())
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
if err := operatorHTTP.InitConfiguration(&cmdMain); err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Command() *cobra.Command {
|
func Command() *cobra.Command {
|
||||||
|
|
|
@ -22,12 +22,9 @@ package deployment
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
nhttp "net/http"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
|
||||||
|
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
apiErrors "k8s.io/apimachinery/pkg/api/errors"
|
apiErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
@ -53,9 +50,11 @@ import (
|
||||||
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
|
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/operator/scope"
|
"github.com/arangodb/kube-arangodb/pkg/operator/scope"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/replication"
|
"github.com/arangodb/kube-arangodb/pkg/replication"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/constants"
|
"github.com/arangodb/kube-arangodb/pkg/util/constants"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/globals"
|
"github.com/arangodb/kube-arangodb/pkg/util/globals"
|
||||||
|
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
|
inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
|
||||||
persistentvolumeclaimv1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/persistentvolumeclaim/v1"
|
persistentvolumeclaimv1 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/persistentvolumeclaim/v1"
|
||||||
|
@ -219,24 +218,7 @@ func (d *Deployment) GetAgency(ctx context.Context, agencyIDs ...string) (agency
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) getConnConfig() (http.ConnectionConfig, error) {
|
func (d *Deployment) getConnConfig() (http.ConnectionConfig, error) {
|
||||||
transport := &nhttp.Transport{
|
transport := operatorHTTP.RoundTripperWithShortTransport(operatorHTTP.WithTransportTLS(util.BoolSwitch(d.GetSpec().TLS.IsSecure(), operatorHTTP.Insecure, nil)))
|
||||||
Proxy: nhttp.ProxyFromEnvironment,
|
|
||||||
DialContext: (&net.Dialer{
|
|
||||||
Timeout: 10 * time.Second,
|
|
||||||
KeepAlive: 100 * time.Millisecond,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 100 * time.Millisecond,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
if d.GetSpec().TLS.IsSecure() {
|
|
||||||
transport.TLSClientConfig = &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
connConfig := http.ConnectionConfig{
|
connConfig := http.ConnectionConfig{
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//
|
//
|
||||||
// DISCLAIMER
|
// DISCLAIMER
|
||||||
//
|
//
|
||||||
// Copyright 2016-2023 ArangoDB GmbH, Cologne, Germany
|
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -43,6 +43,7 @@ import (
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/constants"
|
"github.com/arangodb/kube-arangodb/pkg/util/constants"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/crypto"
|
"github.com/arangodb/kube-arangodb/pkg/util/crypto"
|
||||||
|
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
|
inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
|
||||||
memberTls "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/tls"
|
memberTls "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/tls"
|
||||||
|
@ -450,10 +451,7 @@ func checkServerValidCertRequest(ctx context.Context, context PlanBuilderContext
|
||||||
endpoint = fmt.Sprintf("https://%s:%d%s", k8sutil.CreatePodDNSNameWithDomain(apiObject, context.GetSpec().ClusterDomain, group.AsRole(), member.ID), shared.ArangoSyncMasterPort, shared.ArangoSyncStatusEndpoint)
|
endpoint = fmt.Sprintf("https://%s:%d%s", k8sutil.CreatePodDNSNameWithDomain(apiObject, context.GetSpec().ClusterDomain, group.AsRole(), member.ID), shared.ArangoSyncMasterPort, shared.ArangoSyncStatusEndpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConfig := &tls.Config{
|
transport := operatorHTTP.RoundTripper(operatorHTTP.WithTransportTLS(operatorHTTP.WithRootCA(ca.AsCertPool())))
|
||||||
RootCAs: ca.AsCertPool(),
|
|
||||||
}
|
|
||||||
transport := &http.Transport{TLSClientConfig: tlsConfig}
|
|
||||||
client := &http.Client{Transport: transport, Timeout: time.Second}
|
client := &http.Client{Transport: transport, Timeout: time.Second}
|
||||||
|
|
||||||
auth, err := context.GetAuthentication()()
|
auth, err := context.GetAuthentication()()
|
||||||
|
|
|
@ -21,14 +21,15 @@
|
||||||
package exporter
|
package exporter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||||
|
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ http.Handler = &passthru{}
|
var _ http.Handler = &passthru{}
|
||||||
|
@ -44,17 +45,13 @@ type httpClientFactory func(endpoint string) (*http.Client, *http.Request, error
|
||||||
|
|
||||||
func newHttpClientFactory(auth Authentication, sslVerify bool, timeout time.Duration) httpClientFactory {
|
func newHttpClientFactory(auth Authentication, sslVerify bool, timeout time.Duration) httpClientFactory {
|
||||||
return func(endpoint string) (*http.Client, *http.Request, error) {
|
return func(endpoint string) (*http.Client, *http.Request, error) {
|
||||||
transport := &http.Transport{}
|
transport := operatorHTTP.Transport(operatorHTTP.WithTransportTLS(util.BoolSwitch(sslVerify, operatorHTTP.Insecure, nil)))
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", endpoint, nil)
|
req, err := http.NewRequest("GET", endpoint, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.WithStack(err)
|
return nil, nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !sslVerify {
|
|
||||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
|
||||||
}
|
|
||||||
|
|
||||||
jwt, err := auth()
|
jwt, err := auth()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|
|
@ -23,16 +23,15 @@ package client
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/storage/provisioner"
|
"github.com/arangodb/kube-arangodb/pkg/storage/provisioner"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||||
|
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New creates a new client for the provisioner API.
|
// New creates a new client for the provisioner API.
|
||||||
|
@ -44,39 +43,23 @@ func New(endpoint string) (provisioner.API, error) {
|
||||||
u.Path = ""
|
u.Path = ""
|
||||||
return &client{
|
return &client{
|
||||||
endpoint: *u,
|
endpoint: *u,
|
||||||
|
client: &http.Client{
|
||||||
|
Transport: operatorHTTP.RoundTripper(operatorHTTP.WithTransportTLS(operatorHTTP.Insecure)),
|
||||||
|
Timeout: defaultHTTPTimeout,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
endpoint url.URL
|
endpoint url.URL
|
||||||
|
|
||||||
|
client *http.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultHTTPTimeout = time.Minute * 2
|
defaultHTTPTimeout = time.Minute * 2
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
httpClient = &http.Client{
|
|
||||||
Timeout: defaultHTTPTimeout,
|
|
||||||
Transport: &http.Transport{
|
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
DialContext: (&net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
MaxIdleConnsPerHost: 10,
|
|
||||||
IdleConnTimeout: 90 * time.Second,
|
|
||||||
TLSHandshakeTimeout: 90 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
},
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetNodeInfo fetches information from the current node.
|
// GetNodeInfo fetches information from the current node.
|
||||||
func (c *client) GetNodeInfo(ctx context.Context) (provisioner.NodeInfo, error) {
|
func (c *client) GetNodeInfo(ctx context.Context) (provisioner.NodeInfo, error) {
|
||||||
req, err := c.newRequest("GET", "/nodeinfo", nil)
|
req, err := c.newRequest("GET", "/nodeinfo", nil)
|
||||||
|
@ -165,7 +148,7 @@ func (c *client) newRequest(method string, localPath string, body interface{}) (
|
||||||
// do performs the given request and parses the result.
|
// do performs the given request and parses the result.
|
||||||
func (c *client) do(ctx context.Context, req *http.Request, result interface{}) error {
|
func (c *client) do(ctx context.Context, req *http.Request, result interface{}) error {
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
resp, err := httpClient.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Request failed
|
// Request failed
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
|
|
|
@ -22,11 +22,9 @@ package arangod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"net"
|
"net"
|
||||||
nhttp "net/http"
|
nhttp "net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
|
||||||
|
|
||||||
typedCore "k8s.io/client-go/kubernetes/typed/core/v1"
|
typedCore "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
|
||||||
|
@ -39,6 +37,7 @@ import (
|
||||||
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
shared "github.com/arangodb/kube-arangodb/pkg/apis/shared"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
"github.com/arangodb/kube-arangodb/pkg/util/errors"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/globals"
|
"github.com/arangodb/kube-arangodb/pkg/util/globals"
|
||||||
|
operatorHTTP "github.com/arangodb/kube-arangodb/pkg/util/http"
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -61,58 +60,21 @@ func WithRequireAuthentication(ctx context.Context) context.Context {
|
||||||
return context.WithValue(ctx, requireAuthenticationKey{}, true)
|
return context.WithValue(ctx, requireAuthenticationKey{}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
func sharedHTTPTransport() nhttp.RoundTripper {
|
||||||
sharedHTTPTransport = &nhttp.Transport{
|
return operatorHTTP.Transport()
|
||||||
Proxy: nhttp.ProxyFromEnvironment,
|
|
||||||
DialContext: (&net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 90 * time.Second,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 90 * time.Second,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
}
|
}
|
||||||
sharedHTTPSTransport = &nhttp.Transport{
|
|
||||||
Proxy: nhttp.ProxyFromEnvironment,
|
func sharedHTTPSTransport() nhttp.RoundTripper {
|
||||||
DialContext: (&net.Dialer{
|
return operatorHTTP.Transport(operatorHTTP.WithTransportTLS(operatorHTTP.Insecure))
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 90 * time.Second,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 90 * time.Second,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
}
|
||||||
sharedHTTPTransportShortTimeout = &nhttp.Transport{
|
|
||||||
Proxy: nhttp.ProxyFromEnvironment,
|
func sharedHTTPTransportShortTimeout() nhttp.RoundTripper {
|
||||||
DialContext: (&net.Dialer{
|
return operatorHTTP.RoundTripperWithShortTransport()
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 100 * time.Millisecond,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 100 * time.Millisecond,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
}
|
}
|
||||||
sharedHTTPSTransportShortTimeout = &nhttp.Transport{
|
|
||||||
Proxy: nhttp.ProxyFromEnvironment,
|
func sharedHTTPSTransportShortTimeout() nhttp.RoundTripper {
|
||||||
DialContext: (&net.Dialer{
|
return operatorHTTP.RoundTripperWithShortTransport(operatorHTTP.WithTransportTLS(operatorHTTP.Insecure))
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 100 * time.Millisecond,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 100,
|
|
||||||
IdleConnTimeout: 100 * time.Millisecond,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
ExpectContinueTimeout: 1 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// CreateArangodClient creates a go-driver client for a specific member in the given group.
|
// CreateArangodClient creates a go-driver client for a specific member in the given group.
|
||||||
func CreateArangodClient(ctx context.Context, cli typedCore.CoreV1Interface, apiObject *api.ArangoDeployment, group api.ServerGroup, id string, asyncSupport bool) (driver.Client, error) {
|
func CreateArangodClient(ctx context.Context, cli typedCore.CoreV1Interface, apiObject *api.ArangoDeployment, group api.ServerGroup, id string, asyncSupport bool) (driver.Client, error) {
|
||||||
|
@ -192,7 +154,7 @@ func createArangodHTTPConfigForDNSNames(apiObject *api.ArangoDeployment, dnsName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
connConfig := http.ConnectionConfig{
|
connConfig := http.ConnectionConfig{
|
||||||
Transport: transport,
|
Transport: transport(),
|
||||||
DontFollowRedirect: true,
|
DontFollowRedirect: true,
|
||||||
}
|
}
|
||||||
for _, dnsName := range dnsNames {
|
for _, dnsName := range dnsNames {
|
||||||
|
|
53
pkg/util/http/client.go
Normal file
53
pkg/util/http/client.go
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RoundTripper(mods ...TransportMod) http.RoundTripper {
|
||||||
|
df := append([]TransportMod{
|
||||||
|
configuration.DefaultTransport,
|
||||||
|
}, mods...)
|
||||||
|
|
||||||
|
return Transport(df...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RoundTripperWithShortTransport(mods ...TransportMod) http.RoundTripper {
|
||||||
|
df := append([]TransportMod{
|
||||||
|
configuration.ShortTransport,
|
||||||
|
}, mods...)
|
||||||
|
|
||||||
|
return Transport(df...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Insecure(in *tls.Config) {
|
||||||
|
in.InsecureSkipVerify = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithRootCA(ca *x509.CertPool) TransportTLSMod {
|
||||||
|
return func(in *tls.Config) {
|
||||||
|
in.RootCAs = ca
|
||||||
|
}
|
||||||
|
}
|
140
pkg/util/http/client_configuration.go
Normal file
140
pkg/util/http/client_configuration.go
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitConfiguration(cmd *cobra.Command) error {
|
||||||
|
return configuration.Init(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultTransportKeepAlive bool = true
|
||||||
|
defaultTransportForceAttemptHTTP2 bool = false
|
||||||
|
|
||||||
|
defaultTransportMaxIdleConns int = 100
|
||||||
|
|
||||||
|
defaultTransportDialTimeout = 30 * time.Second
|
||||||
|
defaultTransportKeepAliveTimeout = 90 * time.Second
|
||||||
|
defaultTransportKeepAliveTimeoutShort = 100 * time.Millisecond
|
||||||
|
defaultTransportIdleConnTimeout = 90 * time.Second
|
||||||
|
defaultTransportIdleConnTimeoutShort = 100 * time.Millisecond
|
||||||
|
defaultTransportTLSHandshakeTimeout = 10 * time.Second
|
||||||
|
defaultTransportExpectContinueTimeout = 1 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
var configuration = configurationObject{
|
||||||
|
TransportKeepAlive: defaultTransportKeepAlive,
|
||||||
|
TransportForceAttemptHTTP2: defaultTransportForceAttemptHTTP2,
|
||||||
|
TransportMaxIdleConns: defaultTransportMaxIdleConns,
|
||||||
|
TransportDialTimeout: defaultTransportDialTimeout,
|
||||||
|
TransportKeepAliveTimeout: defaultTransportKeepAliveTimeout,
|
||||||
|
TransportKeepAliveTimeoutShort: defaultTransportKeepAliveTimeoutShort,
|
||||||
|
TransportIdleConnTimeout: defaultTransportIdleConnTimeout,
|
||||||
|
TransportIdleConnTimeoutShort: defaultTransportIdleConnTimeoutShort,
|
||||||
|
TransportTLSHandshakeTimeout: defaultTransportTLSHandshakeTimeout,
|
||||||
|
TransportExpectContinueTimeout: defaultTransportExpectContinueTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
type configurationObject struct {
|
||||||
|
TransportKeepAlive bool
|
||||||
|
TransportForceAttemptHTTP2 bool
|
||||||
|
|
||||||
|
TransportMaxIdleConns int
|
||||||
|
|
||||||
|
TransportDialTimeout time.Duration
|
||||||
|
TransportKeepAliveTimeout time.Duration
|
||||||
|
TransportKeepAliveTimeoutShort time.Duration
|
||||||
|
TransportIdleConnTimeout time.Duration
|
||||||
|
TransportIdleConnTimeoutShort time.Duration
|
||||||
|
TransportTLSHandshakeTimeout time.Duration
|
||||||
|
TransportExpectContinueTimeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configurationObject) Init(cmd *cobra.Command) error {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f := cmd.PersistentFlags()
|
||||||
|
|
||||||
|
f.BoolVar(&configuration.TransportKeepAlive, "http1.keep-alive", defaultTransportKeepAlive, "If false, disables HTTP keep-alives and will only use the connection to the server for a single HTTP request")
|
||||||
|
f.BoolVar(&configuration.TransportForceAttemptHTTP2, "http1.force-attempt-http2", defaultTransportForceAttemptHTTP2, "controls whether HTTP/2 is enabled")
|
||||||
|
|
||||||
|
f.IntVar(&configuration.TransportMaxIdleConns, "http1.transport.max-idle-conns", defaultTransportMaxIdleConns, "Maximum number of idle (keep-alive) connections across all hosts. Zero means no limit")
|
||||||
|
|
||||||
|
f.DurationVar(&configuration.TransportDialTimeout, "http1.transport.dial-timeout", defaultTransportDialTimeout, "Maximum amount of time a dial will wait for a connect to complete")
|
||||||
|
f.DurationVar(&configuration.TransportKeepAliveTimeout, "http1.transport.keep-alive-timeout", defaultTransportKeepAliveTimeout, "Interval between keep-alive probes for an active network connection")
|
||||||
|
f.DurationVar(&configuration.TransportKeepAliveTimeoutShort, "http1.transport.keep-alive-timeout-short", defaultTransportKeepAliveTimeoutShort, "Interval between keep-alive probes for an active network connection")
|
||||||
|
|
||||||
|
f.DurationVar(&configuration.TransportIdleConnTimeout, "http1.transport.idle-conn-timeout", defaultTransportIdleConnTimeout, "Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit")
|
||||||
|
f.DurationVar(&configuration.TransportIdleConnTimeoutShort, "http1.transport.idle-conn-timeout-short", defaultTransportIdleConnTimeoutShort, "Maximum amount of time an idle (keep-alive) connection will remain idle before closing itself. Zero means no limit")
|
||||||
|
f.DurationVar(&configuration.TransportTLSHandshakeTimeout, "http1.transport.tls-handshake-timeout", defaultTransportTLSHandshakeTimeout, "Maximum amount of time to wait for a TLS handshake. Zero means no timeout")
|
||||||
|
f.DurationVar(&configuration.TransportExpectContinueTimeout, "http1.transport.except-continue-timeout", defaultTransportExpectContinueTimeout, "")
|
||||||
|
|
||||||
|
if err := f.MarkHidden("http1.transport.except-continue-timeout"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.MarkHidden("http1.force-attempt-http2"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configurationObject) DefaultTransport(in *http.Transport) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
in.Proxy = http.ProxyFromEnvironment
|
||||||
|
in.ForceAttemptHTTP2 = c.TransportForceAttemptHTTP2
|
||||||
|
in.DialContext = (&net.Dialer{
|
||||||
|
Timeout: c.TransportDialTimeout,
|
||||||
|
KeepAlive: c.TransportKeepAliveTimeout,
|
||||||
|
DualStack: true,
|
||||||
|
}).DialContext
|
||||||
|
|
||||||
|
in.MaxIdleConns = c.TransportMaxIdleConns
|
||||||
|
in.IdleConnTimeout = c.TransportIdleConnTimeout
|
||||||
|
in.TLSHandshakeTimeout = c.TransportTLSHandshakeTimeout
|
||||||
|
in.ExpectContinueTimeout = c.TransportExpectContinueTimeout
|
||||||
|
in.DisableKeepAlives = !c.TransportKeepAlive
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *configurationObject) ShortTransport(in *http.Transport) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
in.DialContext = (&net.Dialer{
|
||||||
|
Timeout: c.TransportDialTimeout,
|
||||||
|
KeepAlive: c.TransportKeepAliveTimeoutShort,
|
||||||
|
DualStack: true,
|
||||||
|
}).DialContext
|
||||||
|
|
||||||
|
in.IdleConnTimeout = c.TransportIdleConnTimeoutShort
|
||||||
|
}
|
57
pkg/util/http/client_mod.go
Normal file
57
pkg/util/http/client_mod.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// DISCLAIMER
|
||||||
|
//
|
||||||
|
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||||
|
//
|
||||||
|
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Mod[T any] func(in T)
|
||||||
|
|
||||||
|
type TransportMod Mod[*http.Transport]
|
||||||
|
|
||||||
|
type TransportTLSMod Mod[*tls.Config]
|
||||||
|
|
||||||
|
func Transport(mods ...TransportMod) http.RoundTripper {
|
||||||
|
var c http.Transport
|
||||||
|
|
||||||
|
for _, m := range mods {
|
||||||
|
if m == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m(&c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithTransportTLS(mods ...TransportTLSMod) TransportMod {
|
||||||
|
return func(in *http.Transport) {
|
||||||
|
if in.TLSClientConfig == nil {
|
||||||
|
in.TLSClientConfig = &tls.Config{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mod := range mods {
|
||||||
|
mod(in.TLSClientConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue