2023-02-02 17:15:17 -08:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2020-05-04 10:58:03 -04:00
|
|
|
package api
|
|
|
|
|
|
|
|
|
|
import (
|
2025-01-08 10:07:09 -05:00
|
|
|
"crypto/tls"
|
2024-08-16 13:42:01 +01:00
|
|
|
"math"
|
2025-01-08 10:07:09 -05:00
|
|
|
"net/http"
|
2024-08-16 13:42:01 +01:00
|
|
|
"os"
|
|
|
|
|
"strconv"
|
2020-05-04 10:58:03 -04:00
|
|
|
"testing"
|
2025-01-08 10:07:09 -05:00
|
|
|
"time"
|
2020-05-04 10:58:03 -04:00
|
|
|
|
2025-01-08 10:07:09 -05:00
|
|
|
"github.com/google/go-cmp/cmp"
|
|
|
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
|
|
|
"github.com/hashicorp/go-cleanhttp"
|
2020-05-04 10:58:03 -04:00
|
|
|
"github.com/stretchr/testify/assert"
|
2024-08-16 13:42:01 +01:00
|
|
|
"github.com/stretchr/testify/require"
|
2020-05-04 10:58:03 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestConfigSetAddress(t *testing.T) {
|
|
|
|
|
type test struct {
|
2023-11-13 13:36:28 -08:00
|
|
|
name string
|
|
|
|
|
input string
|
|
|
|
|
address string
|
|
|
|
|
err string
|
2020-05-04 10:58:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tests := []test{
|
|
|
|
|
{
|
2024-09-19 08:55:27 -07:00
|
|
|
"ipv4",
|
2023-11-13 13:36:28 -08:00
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
2024-09-19 08:55:27 -07:00
|
|
|
{
|
|
|
|
|
"ipv6",
|
|
|
|
|
"http://[::1]:9200",
|
|
|
|
|
"http://[::1]:9200",
|
|
|
|
|
"",
|
|
|
|
|
},
|
2020-05-04 10:58:03 -04:00
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"bare with version",
|
|
|
|
|
"http://127.0.0.1:9200/v1",
|
|
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
|
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"bare with version and trailing slash",
|
|
|
|
|
"http://127.0.0.1:9200/v1/",
|
|
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
|
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"valid top level scope",
|
|
|
|
|
"http://127.0.0.1:9200/v1/scopes",
|
|
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
|
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"valid scope",
|
|
|
|
|
"http://127.0.0.1:9200/v1/scopes/scopeid",
|
|
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
|
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"longer path project",
|
|
|
|
|
"http://127.0.0.1:9200/v1/auth-methods",
|
|
|
|
|
"http://127.0.0.1:9200",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
|
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"valid project",
|
|
|
|
|
"http://127.0.0.1:9200/my-install",
|
|
|
|
|
"http://127.0.0.1:9200/my-install",
|
|
|
|
|
"",
|
2020-05-04 10:58:03 -04:00
|
|
|
},
|
2022-02-16 10:15:02 -05:00
|
|
|
{
|
2023-11-13 13:36:28 -08:00
|
|
|
"valid project path containing v1",
|
|
|
|
|
"http://127.0.0.1:9200/randomPathHasv1InIt",
|
|
|
|
|
"http://127.0.0.1:9200/randomPathHasv1InIt",
|
|
|
|
|
"",
|
2022-02-16 10:15:02 -05:00
|
|
|
},
|
2020-05-04 10:58:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, v := range tests {
|
|
|
|
|
t.Run(v.name, func(t *testing.T) {
|
|
|
|
|
var c Config
|
2020-05-08 12:03:56 -04:00
|
|
|
err := c.setAddr(v.input)
|
2023-11-13 13:36:28 -08:00
|
|
|
if err != nil {
|
|
|
|
|
assert.Equal(t, v.err, err.Error())
|
|
|
|
|
}
|
2020-05-08 12:03:56 -04:00
|
|
|
assert.Equal(t, v.address, c.Addr)
|
2020-05-04 10:58:03 -04:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-08-16 13:42:01 +01:00
|
|
|
|
|
|
|
|
func TestReadEnvironmentMaxRetries(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
inp string
|
|
|
|
|
expMaxRetries int
|
|
|
|
|
expErrContains string
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "invalidNaN",
|
|
|
|
|
inp: "bad",
|
|
|
|
|
expErrContains: "strconv.ParseUint: parsing \"bad\": invalid syntax",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "invalidNegativeNumber",
|
|
|
|
|
inp: "-1",
|
|
|
|
|
expErrContains: "strconv.ParseUint: parsing \"-1\": invalid syntax",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "invalidGreaterThanUint32",
|
|
|
|
|
inp: strconv.Itoa(math.MaxUint32 + 10),
|
|
|
|
|
expErrContains: "strconv.ParseUint: parsing \"4294967305\": value out of range",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "invalidGreaterThanInt32",
|
|
|
|
|
inp: strconv.Itoa(math.MaxInt32 + 10),
|
|
|
|
|
expErrContains: "max retries must be less than or equal to 2147483647",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "success1",
|
|
|
|
|
inp: "0",
|
|
|
|
|
expMaxRetries: 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "success2",
|
|
|
|
|
inp: "10000",
|
|
|
|
|
expMaxRetries: 10000,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "successMaxInt32",
|
|
|
|
|
inp: strconv.Itoa(math.MaxInt32),
|
|
|
|
|
expMaxRetries: math.MaxInt32,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "successNothing",
|
|
|
|
|
inp: "",
|
|
|
|
|
expMaxRetries: 0,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
os.Setenv(EnvBoundaryMaxRetries, tt.inp)
|
|
|
|
|
t.Cleanup(func() { os.Unsetenv(EnvBoundaryMaxRetries) })
|
|
|
|
|
|
|
|
|
|
var c Config
|
|
|
|
|
err := c.ReadEnvironment()
|
|
|
|
|
if tt.expErrContains != "" {
|
|
|
|
|
require.ErrorContains(t, err, tt.expErrContains)
|
|
|
|
|
require.Equal(t, 0, c.MaxRetries)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Equal(t, tt.expMaxRetries, c.MaxRetries)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-08 10:07:09 -05:00
|
|
|
|
|
|
|
|
func TestDefaultConfig(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
envvars map[string]string
|
|
|
|
|
want *Config
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "noEnvVarsSet",
|
|
|
|
|
envvars: nil,
|
|
|
|
|
want: &Config{
|
|
|
|
|
Addr: "http://127.0.0.1:9200",
|
|
|
|
|
Token: "",
|
|
|
|
|
RecoveryKmsWrapper: nil,
|
|
|
|
|
HttpClient: func() *http.Client {
|
|
|
|
|
client := cleanhttp.DefaultPooledClient()
|
|
|
|
|
client.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
|
|
|
|
|
MinVersion: tls.VersionTLS12,
|
|
|
|
|
}
|
|
|
|
|
return client
|
|
|
|
|
}(),
|
|
|
|
|
TLSConfig: &TLSConfig{},
|
|
|
|
|
Headers: map[string][]string{},
|
|
|
|
|
MaxRetries: 2,
|
|
|
|
|
Timeout: time.Second * 60,
|
|
|
|
|
Backoff: RateLimitLinearJitterBackoff,
|
|
|
|
|
CheckRetry: nil,
|
|
|
|
|
Limiter: nil,
|
|
|
|
|
OutputCurlString: false,
|
|
|
|
|
SRVLookup: false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "maxRetries",
|
|
|
|
|
envvars: map[string]string{
|
|
|
|
|
"BOUNDARY_MAX_RETRIES": "5",
|
|
|
|
|
},
|
|
|
|
|
want: &Config{
|
|
|
|
|
Addr: "http://127.0.0.1:9200",
|
|
|
|
|
Token: "",
|
|
|
|
|
RecoveryKmsWrapper: nil,
|
|
|
|
|
HttpClient: func() *http.Client {
|
|
|
|
|
client := cleanhttp.DefaultPooledClient()
|
|
|
|
|
client.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
|
|
|
|
|
MinVersion: tls.VersionTLS12,
|
|
|
|
|
}
|
|
|
|
|
return client
|
|
|
|
|
}(),
|
|
|
|
|
TLSConfig: &TLSConfig{},
|
|
|
|
|
Headers: map[string][]string{},
|
|
|
|
|
MaxRetries: 5,
|
|
|
|
|
Timeout: time.Second * 60,
|
|
|
|
|
Backoff: RateLimitLinearJitterBackoff,
|
|
|
|
|
CheckRetry: nil,
|
|
|
|
|
Limiter: nil,
|
|
|
|
|
OutputCurlString: false,
|
|
|
|
|
SRVLookup: false,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
for k, v := range tt.envvars {
|
|
|
|
|
os.Setenv(k, v)
|
|
|
|
|
}
|
|
|
|
|
t.Cleanup(func() {
|
|
|
|
|
for k := range tt.envvars {
|
|
|
|
|
os.Unsetenv(k)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
c, err := DefaultConfig()
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
assert.Empty(t,
|
|
|
|
|
cmp.Diff(tt.want, c,
|
|
|
|
|
cmpopts.IgnoreUnexported(http.Transport{}, tls.Config{}),
|
|
|
|
|
// Ignore fields that are functions, since cmp.Diff can't
|
|
|
|
|
// correctly compare them if they are non-nil.
|
|
|
|
|
cmpopts.IgnoreFields(Config{}, "Backoff"),
|
|
|
|
|
cmpopts.IgnoreFields(http.Transport{}, "Proxy", "DialContext"),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
}
|