test: slight refactoring ahead of peering testing improvements (#17387)
This commit is contained in:
parent
4859cfb47b
commit
00a9e03f44
|
@ -6,6 +6,7 @@ package assert
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -14,15 +15,29 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/sdk/testutil/retry"
|
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||||
libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster"
|
|
||||||
"github.com/hashicorp/consul/test/integration/consul-container/libs/utils"
|
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
libcluster "github.com/hashicorp/consul/test/integration/consul-container/libs/cluster"
|
||||||
|
"github.com/hashicorp/consul/test/integration/consul-container/libs/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetEnvoyListenerTCPFilters validates that proxy was configured with tcp protocol and one rbac listener filter
|
// GetEnvoyListenerTCPFilters validates that proxy was configured with tcp protocol and one rbac listener filter
|
||||||
func GetEnvoyListenerTCPFilters(t *testing.T, adminPort int) {
|
func GetEnvoyListenerTCPFilters(t *testing.T, adminPort int) {
|
||||||
|
require.True(t, adminPort > 0)
|
||||||
|
|
||||||
|
GetEnvoyListenerTCPFiltersWithClient(
|
||||||
|
t,
|
||||||
|
cleanhttp.DefaultClient(),
|
||||||
|
fmt.Sprintf("localhost:%d", adminPort),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
func GetEnvoyListenerTCPFiltersWithClient(
|
||||||
|
t *testing.T,
|
||||||
|
client *http.Client,
|
||||||
|
addr string,
|
||||||
|
) {
|
||||||
var (
|
var (
|
||||||
dump string
|
dump string
|
||||||
err error
|
err error
|
||||||
|
@ -32,7 +47,7 @@ func GetEnvoyListenerTCPFilters(t *testing.T, adminPort int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
retry.RunWith(failer(), t, func(r *retry.R) {
|
retry.RunWith(failer(), t, func(r *retry.R) {
|
||||||
dump, _, err = GetEnvoyOutput(adminPort, "config_dump", map[string]string{})
|
dump, _, err = GetEnvoyOutputWithClient(client, addr, "config_dump", map[string]string{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatal("could not fetch envoy configuration")
|
r.Fatal("could not fetch envoy configuration")
|
||||||
}
|
}
|
||||||
|
@ -55,30 +70,55 @@ func GetEnvoyListenerTCPFilters(t *testing.T, adminPort int) {
|
||||||
require.Contains(t, filteredResult, "envoy.filters.network.tcp_proxy")
|
require.Contains(t, filteredResult, "envoy.filters.network.tcp_proxy")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func GetEnvoyOutputWithClient(client *http.Client, addr string, path string, query map[string]string) (string, int, error) {
|
||||||
|
|
||||||
// AssertUpstreamEndpointStatus validates that proxy was configured with provided clusterName in the healthStatus
|
// AssertUpstreamEndpointStatus validates that proxy was configured with provided clusterName in the healthStatus
|
||||||
func AssertUpstreamEndpointStatus(t *testing.T, adminPort int, clusterName, healthStatus string, count int) {
|
func AssertUpstreamEndpointStatus(t *testing.T, adminPort int, clusterName, healthStatus string, count int) {
|
||||||
var (
|
require.True(t, adminPort > 0)
|
||||||
clusters string
|
AssertUpstreamEndpointStatusWithClient(
|
||||||
err error
|
t,
|
||||||
|
cleanhttp.DefaultClient(),
|
||||||
|
fmt.Sprintf("localhost:%d", adminPort),
|
||||||
|
clusterName,
|
||||||
|
healthStatus,
|
||||||
|
count,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
func AssertUpstreamEndpointStatusWithClient(
|
||||||
|
t *testing.T,
|
||||||
|
client *http.Client,
|
||||||
|
addr string,
|
||||||
|
clusterName string,
|
||||||
|
healthStatus string,
|
||||||
|
count int,
|
||||||
|
) {
|
||||||
|
require.NotNil(t, client)
|
||||||
|
require.NotEmpty(t, addr)
|
||||||
failer := func() *retry.Timer {
|
failer := func() *retry.Timer {
|
||||||
return &retry.Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond}
|
return &retry.Timer{Timeout: 30 * time.Second, Wait: 500 * time.Millisecond}
|
||||||
}
|
}
|
||||||
|
|
||||||
retry.RunWith(failer(), t, func(r *retry.R) {
|
retry.RunWith(failer(), t, func(r *retry.R) {
|
||||||
clusters, _, err = GetEnvoyOutput(adminPort, "clusters", map[string]string{"format": "json"})
|
clusters, statusCode, err := GetEnvoyOutputWithClient(client, addr, "clusters", map[string]string{"format": "json"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatal("could not fetch envoy clusters")
|
r.Fatal("could not fetch envoy clusters")
|
||||||
}
|
}
|
||||||
|
require.Equal(r, 200, statusCode)
|
||||||
|
|
||||||
filter := fmt.Sprintf(`.cluster_statuses[] | select(.name|contains("%s")) | [.host_statuses[].health_status.eds_health_status] | [select(.[] == "%s")] | length`, clusterName, healthStatus)
|
filter := fmt.Sprintf(
|
||||||
|
`.cluster_statuses[]
|
||||||
|
| select(.name|contains("%s"))
|
||||||
|
| [.host_statuses[].health_status.eds_health_status]
|
||||||
|
| [select(.[] == "%s")]
|
||||||
|
| length`,
|
||||||
|
clusterName, healthStatus)
|
||||||
results, err := utils.JQFilter(clusters, filter)
|
results, err := utils.JQFilter(clusters, filter)
|
||||||
require.NoErrorf(r, err, "could not found cluster name %s", clusterName)
|
require.NoErrorf(r, err, "could not found cluster name %s in \n%s", clusterName, clusters)
|
||||||
|
require.Len(r, results, 1) // the final part of the pipeline is "length" which only ever returns 1 result
|
||||||
|
|
||||||
resultToString := strings.Join(results, " ")
|
result, err := strconv.Atoi(results[0])
|
||||||
result, err := strconv.Atoi(resultToString)
|
|
||||||
assert.NoError(r, err)
|
assert.NoError(r, err)
|
||||||
require.Equal(r, count, result)
|
require.Equal(r, count, result, "original results: %v", clusters)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,8 +280,12 @@ func AssertEnvoyRunning(t *testing.T, port int) {
|
||||||
|
|
||||||
func GetEnvoyOutput(port int, path string, query map[string]string) (string, int, error) {
|
func GetEnvoyOutput(port int, path string, query map[string]string) (string, int, error) {
|
||||||
client := cleanhttp.DefaultClient()
|
client := cleanhttp.DefaultClient()
|
||||||
|
return GetEnvoyOutputWithClient(client, fmt.Sprintf("localhost:%d", port), path, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetEnvoyOutputWithClient(client *http.Client, addr string, path string, query map[string]string) (string, int, error) {
|
||||||
var u url.URL
|
var u url.URL
|
||||||
u.Host = fmt.Sprintf("localhost:%d", port)
|
u.Host = addr
|
||||||
u.Scheme = "http"
|
u.Scheme = "http"
|
||||||
if path != "" {
|
if path != "" {
|
||||||
u.Path = path
|
u.Path = path
|
||||||
|
|
|
@ -14,15 +14,24 @@ import (
|
||||||
|
|
||||||
// PeeringStatus verifies the peering connection is the specified state with a default retry.
|
// PeeringStatus verifies the peering connection is the specified state with a default retry.
|
||||||
func PeeringStatus(t *testing.T, client *api.Client, peerName string, status api.PeeringState) {
|
func PeeringStatus(t *testing.T, client *api.Client, peerName string, status api.PeeringState) {
|
||||||
|
PeeringStatusOpts(t, client, peerName, status, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeeringStatusOpts verifies the peering connection is the specified
|
||||||
|
// state with a default retry with options.
|
||||||
|
func PeeringStatusOpts(t *testing.T, client *api.Client, peerName string, status api.PeeringState, opts *api.QueryOptions) {
|
||||||
failer := func() *retry.Timer {
|
failer := func() *retry.Timer {
|
||||||
return &retry.Timer{Timeout: 180 * time.Second, Wait: defaultWait}
|
return &retry.Timer{Timeout: 180 * time.Second, Wait: defaultWait}
|
||||||
}
|
}
|
||||||
|
|
||||||
retry.RunWith(failer(), t, func(r *retry.R) {
|
retry.RunWith(failer(), t, func(r *retry.R) {
|
||||||
peering, _, err := client.Peerings().Read(context.Background(), peerName, &api.QueryOptions{})
|
peering, _, err := client.Peerings().Read(context.Background(), peerName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatal("error reading peering data")
|
r.Fatal("error reading peering data")
|
||||||
}
|
}
|
||||||
|
if peering == nil {
|
||||||
|
r.Fatal("peering not found")
|
||||||
|
}
|
||||||
if status != peering.State {
|
if status != peering.State {
|
||||||
r.Fatal("peering state did not match: got ", peering.State, " want ", status)
|
r.Fatal("peering state did not match: got ", peering.State, " want ", status)
|
||||||
}
|
}
|
||||||
|
@ -31,15 +40,24 @@ func PeeringStatus(t *testing.T, client *api.Client, peerName string, status api
|
||||||
|
|
||||||
// PeeringExports verifies the correct number of exported services with a default retry.
|
// PeeringExports verifies the correct number of exported services with a default retry.
|
||||||
func PeeringExports(t *testing.T, client *api.Client, peerName string, exports int) {
|
func PeeringExports(t *testing.T, client *api.Client, peerName string, exports int) {
|
||||||
|
PeeringExportsOpts(t, client, peerName, exports, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeeringExportsOpts verifies the correct number of exported services
|
||||||
|
// with a default retry with options.
|
||||||
|
func PeeringExportsOpts(t *testing.T, client *api.Client, peerName string, exports int, opts *api.QueryOptions) {
|
||||||
failer := func() *retry.Timer {
|
failer := func() *retry.Timer {
|
||||||
return &retry.Timer{Timeout: defaultTimeout, Wait: defaultWait}
|
return &retry.Timer{Timeout: defaultTimeout, Wait: defaultWait}
|
||||||
}
|
}
|
||||||
|
|
||||||
retry.RunWith(failer(), t, func(r *retry.R) {
|
retry.RunWith(failer(), t, func(r *retry.R) {
|
||||||
peering, _, err := client.Peerings().Read(context.Background(), peerName, &api.QueryOptions{})
|
peering, _, err := client.Peerings().Read(context.Background(), peerName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatal("error reading peering data")
|
r.Fatal("error reading peering data")
|
||||||
}
|
}
|
||||||
|
if peering == nil {
|
||||||
|
r.Fatal("peering not found")
|
||||||
|
}
|
||||||
if exports != len(peering.StreamStatus.ExportedServices) {
|
if exports != len(peering.StreamStatus.ExportedServices) {
|
||||||
r.Fatal("peering exported services did not match: got ", len(peering.StreamStatus.ExportedServices), " want ", exports)
|
r.Fatal("peering exported services did not match: got ", len(peering.StreamStatus.ExportedServices), " want ", exports)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,9 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/sdk/testutil/retry"
|
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||||
libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
libservice "github.com/hashicorp/consul/test/integration/consul-container/libs/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -55,22 +56,39 @@ func CatalogNodeExists(t *testing.T, c *api.Client, nodeName string) {
|
||||||
func HTTPServiceEchoes(t *testing.T, ip string, port int, path string) {
|
func HTTPServiceEchoes(t *testing.T, ip string, port int, path string) {
|
||||||
doHTTPServiceEchoes(t, ip, port, path, nil)
|
doHTTPServiceEchoes(t, ip, port, path, nil)
|
||||||
}
|
}
|
||||||
|
func HTTPServiceEchoesWithClient(t *testing.T, client *http.Client, addr string, path string) {
|
||||||
|
doHTTPServiceEchoesWithClient(t, client, addr, path, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func HTTPServiceEchoesResHeader(t *testing.T, ip string, port int, path string, expectedResHeader map[string]string) {
|
func HTTPServiceEchoesResHeader(t *testing.T, ip string, port int, path string, expectedResHeader map[string]string) {
|
||||||
doHTTPServiceEchoes(t, ip, port, path, expectedResHeader)
|
doHTTPServiceEchoes(t, ip, port, path, expectedResHeader)
|
||||||
}
|
}
|
||||||
|
func HTTPServiceEchoesResHeaderWithClient(t *testing.T, client *http.Client, addr string, path string, expectedResHeader map[string]string) {
|
||||||
|
doHTTPServiceEchoesWithClient(t, client, addr, path, expectedResHeader)
|
||||||
|
}
|
||||||
|
|
||||||
// HTTPServiceEchoes verifies that a post to the given ip/port combination returns the data
|
// HTTPServiceEchoes verifies that a post to the given ip/port combination returns the data
|
||||||
// in the response body. Optional path can be provided to differentiate requests.
|
// in the response body. Optional path can be provided to differentiate requests.
|
||||||
func doHTTPServiceEchoes(t *testing.T, ip string, port int, path string, expectedResHeader map[string]string) {
|
func doHTTPServiceEchoes(t *testing.T, ip string, port int, path string, expectedResHeader map[string]string) {
|
||||||
|
client := cleanhttp.DefaultClient()
|
||||||
|
addr := fmt.Sprintf("%s:%d", ip, port)
|
||||||
|
doHTTPServiceEchoesWithClient(t, client, addr, path, expectedResHeader)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doHTTPServiceEchoesWithClient(
|
||||||
|
t *testing.T,
|
||||||
|
client *http.Client,
|
||||||
|
addr string,
|
||||||
|
path string,
|
||||||
|
expectedResHeader map[string]string,
|
||||||
|
) {
|
||||||
const phrase = "hello"
|
const phrase = "hello"
|
||||||
|
|
||||||
failer := func() *retry.Timer {
|
failer := func() *retry.Timer {
|
||||||
return &retry.Timer{Timeout: defaultHTTPTimeout, Wait: defaultHTTPWait}
|
return &retry.Timer{Timeout: defaultHTTPTimeout, Wait: defaultHTTPWait}
|
||||||
}
|
}
|
||||||
|
|
||||||
client := cleanhttp.DefaultClient()
|
url := "http://" + addr
|
||||||
url := fmt.Sprintf("http://%s:%d", ip, port)
|
|
||||||
|
|
||||||
if path != "" {
|
if path != "" {
|
||||||
url += "/" + path
|
url += "/" + path
|
||||||
|
@ -85,6 +103,10 @@ func doHTTPServiceEchoes(t *testing.T, ip string, port int, path string, expecte
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
statusCode := res.StatusCode
|
||||||
|
t.Logf("...got response code %d", statusCode)
|
||||||
|
require.Equal(r, 200, statusCode)
|
||||||
|
|
||||||
body, err := io.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Fatal("could not read response body ", url)
|
r.Fatal("could not read response body ", url)
|
||||||
|
@ -166,7 +188,7 @@ func AssertFortioNameWithClient(t *testing.T, urlbase string, name string, reqHo
|
||||||
|
|
||||||
m := fortioNameRE.FindStringSubmatch(string(body))
|
m := fortioNameRE.FindStringSubmatch(string(body))
|
||||||
require.GreaterOrEqual(r, len(m), 2)
|
require.GreaterOrEqual(r, len(m), 2)
|
||||||
t.Logf("got response from server name %s", m[1])
|
t.Logf("got response from server name %q expect %q", m[1], name)
|
||||||
assert.Equal(r, name, m[1])
|
assert.Equal(r, name, m[1])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "github.com/hashicorp/consul/api"
|
||||||
|
|
||||||
|
func PartitionOrDefault(name string) string {
|
||||||
|
if name == "" {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
func NamespaceOrDefault(name string) string {
|
||||||
|
if name == "" {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultToEmpty(name string) string {
|
||||||
|
if name == "default" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartitionQueryOptions returns an *api.QueryOptions with the given partition
|
||||||
|
// field set only if the partition is non-default. This helps when writing
|
||||||
|
// tests for joint use in OSS and ENT.
|
||||||
|
func PartitionQueryOptions(partition string) *api.QueryOptions {
|
||||||
|
return &api.QueryOptions{
|
||||||
|
Partition: DefaultToEmpty(partition),
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,6 +55,8 @@ func GetLatestImageName() string {
|
||||||
return LatestImageName
|
return LatestImageName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsEnterprise() bool { return isInEnterpriseRepo }
|
||||||
|
|
||||||
func DockerImage(image, version string) string {
|
func DockerImage(image, version string) string {
|
||||||
v := image + ":" + version
|
v := image + ":" + version
|
||||||
if strings.Contains(image, DefaultImageNameENT) && isSemVer(version) {
|
if strings.Contains(image, DefaultImageNameENT) && isSemVer(version) {
|
||||||
|
|
|
@ -9,4 +9,5 @@ package utils
|
||||||
const (
|
const (
|
||||||
defaultImageName = DefaultImageNameOSS
|
defaultImageName = DefaultImageNameOSS
|
||||||
ImageVersionSuffix = ""
|
ImageVersionSuffix = ""
|
||||||
|
isInEnterpriseRepo = false
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue