Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions test/e2e/alerts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import (
func TestAlertmanagerApiProxy(t *testing.T) {
t.Parallel()

e, err := e2e.New(e2e.WithName(envAlertmanagerName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, alerts, e)
_, token, rateLimiterAddr := startBaseServices(t, e, alerts)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
alertmanagerEndpoint := newAlertmanagerService(e)
readEndpoint, writeEndpoint, _ := startServicesForMetrics(t, e)
testutil.Ok(t, e2e.StartAndWaitReady(alertmanagerEndpoint))
Expand Down
11 changes: 0 additions & 11 deletions test/e2e/configs.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,6 @@ const (
certsSharedDir = "certs"
configSharedDir = "config"

envMetricsName = "metrics"
envRulesAPIName = "rules-api"
envAlertmanagerName = "alertmanager-api"
envLogsName = "logs-tail"
envTracesName = "traces-export"
envTracesTempoName = "traces-tempo"
envTracesTemplateName = "traces-template"
envTenantsName = "tenants"
envInteractive = "interactive"
envProbesName = "probes"

defaultTenantID = "1610b0c3-c509-4592-a256-a1871353dbfa"
mtlsTenantID = "845cdfd9-f936-443c-979c-2ee7dc91f646"

Expand Down
73 changes: 39 additions & 34 deletions test/e2e/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package e2e

import (
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/json"
Expand All @@ -21,28 +22,52 @@ import (
"github.com/observatorium/api/test/testtls"
)

// uniqueE2ENetworkName returns a Docker-valid e2e network name (≤16 chars, [-a-zA-Z0-9])
// that is distinct for each Go test. efficientgo/e2e's bare e2e.New() would assign the same
// network to all parallel tests leading to Docker network races.
func uniqueE2ENetworkName(t *testing.T) string {
t.Helper()
sum := sha256.Sum256([]byte(t.Name()))
return fmt.Sprintf("%x", sum[:8]) // 16 hex digits
}

// Generates certificates and copies static configuration to the shared directory.
func prepareConfigsAndCerts(t *testing.T, tt testType, e e2e.Environment) {
func prepareConfigsAndCerts(t *testing.T, e e2e.Environment) {
testutil.Ok(
t,
testtls.GenerateCerts(
filepath.Join(e.SharedDir(), certsSharedDir),
getContainerName(t, tt, "observatorium-api"),
[]string{getContainerName(t, tt, "observatorium-api"), "127.0.0.1"},
getContainerName(t, tt, "dex"),
[]string{getContainerName(t, tt, "dex"), "127.0.0.1"},
getContainerName(e, "observatorium-api"),
[]string{
getContainerName(e, "observatorium-api"),
"127.0.0.1",
"host.docker.internal",
},
getContainerName(e, "dex"),
[]string{
getContainerName(e, "dex"),
"127.0.0.1",
"host.docker.internal",
},
),
)

testutil.Ok(t, exec.Command("cp", "-r", "../config", filepath.Join(e.SharedDir(), configSharedDir)).Run())
}

// obtainToken obtains a bearer token needed for communication with the API.
func obtainToken(endpoint string, tlsConf *tls.Config) (string, error) {
// dexTLSHost is the Dex DNS name from the test CA (e.g. {network}-dex); set it so TLS verifies the
// server cert when the TCP dial target is 127.0.0.1 or host.docker.internal (e2e.Endpoint).
func obtainToken(endpoint, dexTLSHost string, tlsConf *tls.Config) (string, error) {
type token struct {
IDToken string `json:"id_token"`
}

tlsClient := tlsConf.Clone()
if dexTLSHost != "" {
tlsClient.ServerName = dexTLSHost
}

data := url.Values{}
data.Add("grant_type", "password")
data.Add("username", "admin@example.com")
Expand All @@ -59,7 +84,7 @@ func obtainToken(endpoint string, tlsConf *tls.Config) (string, error) {

c := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConf,
TLSClientConfig: tlsClient,
},
}

Expand All @@ -82,40 +107,20 @@ func obtainToken(endpoint string, tlsConf *tls.Config) (string, error) {
return t.IDToken, nil
}

func getContainerName(t *testing.T, tt testType, serviceName string) string {
switch tt {
case logs:
return envLogsName + "-" + serviceName
case metrics:
return envMetricsName + "-" + serviceName
case rules:
return envRulesAPIName + "-" + serviceName
case alerts:
return envAlertmanagerName + "-" + serviceName
case tenants:
return envTenantsName + "-" + serviceName
case interactive:
return envInteractive + "-" + serviceName
case probes:
return envProbesName + "-" + serviceName
case traces:
return envTracesName + "-" + serviceName
case tracesTemplate:
return envTracesTemplateName + "-" + serviceName
case tracesTempo:
return envTracesTempoName + "-" + serviceName
default:
t.Fatal("invalid test type provided")
return ""
}
// getContainerName returns the Docker DNS hostname for a service in this environment.
// It must match e2e's naming ({networkName}-{runnableName}) so TLS SANs and OIDC redirects stay correct.
func getContainerName(e e2e.Environment, serviceName string) string {
return e.Name() + "-" + serviceName
}

func getTLSClientConfig(t *testing.T, e e2e.Environment) *tls.Config {
cert, err := os.ReadFile(filepath.Join(e.SharedDir(), certsSharedDir, "ca.pem"))
testutil.Ok(t, err)

cp := x509.NewCertPool()
cp.AppendCertsFromPEM(cert)
if ok := cp.AppendCertsFromPEM(cert); !ok {
t.Fatal("failed to parse CA certificate from ca.pem")
}

return &tls.Config{
RootCAs: cp,
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/interactive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import (
func TestInteractiveSetup(t *testing.T) {
fmt.Printf("Starting services...\n")

e, err := e2e.New(e2e.WithName(envInteractive))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, interactive, e)
_, token, rateLimiterAddr := startBaseServices(t, e, interactive)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
readEndpoint, writeEndpoint, readExtEndpoint := startServicesForMetrics(t, e)
logsEndpoint, logsExtEndpoint := startServicesForLogs(t, e)
rulesEndpoint := startServicesForRules(t, e)
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import (
func TestLogs(t *testing.T) {
t.Parallel()

e, err := e2e.New(e2e.WithName(envLogsName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, logs, e)
_, token, rateLimiterAddr := startBaseServices(t, e, logs)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
logsEndpoint, logsExtEndpoint := startServicesForLogs(t, e)

api, err := newObservatoriumAPIService(
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import (
func TestMetricsReadAndWrite(t *testing.T) {
t.Parallel()

e, err := e2e.New(e2e.WithName(envMetricsName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, metrics, e)
_, token, rateLimiterAddr := startBaseServices(t, e, metrics)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
readEndpoint, writeEndpoint, readExtEndpoint := startServicesForMetrics(t, e)

api, err := newObservatoriumAPIService(
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/openapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import (
func TestOpenAPIEndpoint(t *testing.T) {
t.Parallel()

e, err := e2e.New(e2e.WithName(envMetricsName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, metrics, e)
_, _, _ = startBaseServices(t, e, metrics)
prepareConfigsAndCerts(t, e)
_, _, _ = startBaseServices(t, e)
readEndpoint, writeEndpoint, _ := startServicesForMetrics(t, e)

api, err := newObservatoriumAPIService(
Expand Down
24 changes: 12 additions & 12 deletions test/e2e/probes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import (
)

func TestProbes_CreateAndGetProbe(t *testing.T) {
e, err := e2e.New(e2e.WithName(envProbesName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, probes, e)
_, token, rateLimiterAddr := startBaseServices(t, e, probes)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
probesEndpoint := startServicesForProbes(t, e)

api, err := newObservatoriumAPIService(
Expand Down Expand Up @@ -112,12 +112,12 @@ func TestProbes_CreateAndGetProbe(t *testing.T) {
}

func TestProbes_ListProbes(t *testing.T) {
e, err := e2e.New(e2e.WithName(envProbesName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, probes, e)
_, token, rateLimiterAddr := startBaseServices(t, e, probes)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
probesEndpoint := startServicesForProbes(t, e)

api, err := newObservatoriumAPIService(
Expand Down Expand Up @@ -218,12 +218,12 @@ func TestProbes_ListProbes(t *testing.T) {
}

func TestProbes_CreateProbeConflict(t *testing.T) {
e, err := e2e.New(e2e.WithName(envProbesName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, probes, e)
_, token, rateLimiterAddr := startBaseServices(t, e, probes)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
probesEndpoint := startServicesForProbes(t, e)

api, err := newObservatoriumAPIService(
Expand Down Expand Up @@ -282,12 +282,12 @@ func TestProbes_CreateProbeConflict(t *testing.T) {
}

func TestProbes_UnauthorizedAccess(t *testing.T) {
e, err := e2e.New(e2e.WithName(envProbesName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, probes, e)
_, _, rateLimiterAddr := startBaseServices(t, e, probes)
prepareConfigsAndCerts(t, e)
_, _, rateLimiterAddr := startBaseServices(t, e)
probesEndpoint := startServicesForProbes(t, e)

api, err := newObservatoriumAPIService(
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/redis_rate_limiter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
func TestRedisRateLimiter_GetRateLimits(t *testing.T) {
t.Parallel()
// Start isolated environment with given ref.
e, err := e2e.New(e2e.WithName("redis-rate-li"))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

Expand Down
6 changes: 3 additions & 3 deletions test/e2e/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ const metricsNilRulesYamlTpl = ``
func TestRulesAPI(t *testing.T) {
t.Parallel()

e, err := e2e.New(e2e.WithName(envRulesAPIName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, rules, e)
_, token, rateLimiterAddr := startBaseServices(t, e, rules)
prepareConfigsAndCerts(t, e)
_, token, rateLimiterAddr := startBaseServices(t, e)
metricsRulesEndpoint := startServicesForRules(t, e)
logsRulesEndpoint, _ := startServicesForLogs(t, e)

Expand Down
8 changes: 4 additions & 4 deletions test/e2e/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,21 +177,21 @@ func startServicesForProbes(t *testing.T, e e2e.Environment) (probesEndpoint str
}

// startBaseServices starts and waits until all base services required for the test are ready.
func startBaseServices(t *testing.T, e e2e.Environment, tt testType) (
func startBaseServices(t *testing.T, e e2e.Environment) (
dex *e2emon.InstrumentedRunnable,
token string,
rateLimiterAddr string,
) {
createDexYAML(t, e, getContainerName(t, tt, "dex"), getContainerName(t, tt, "observatorium_api"))
createDexYAML(t, e, getContainerName(e, "dex"), getContainerName(e, "observatorium-api"))

dex = newDexService(e)
gubernator := newGubernatorService(e)
opa := newOPAService(e)
testutil.Ok(t, e2e.StartAndWaitReady(dex, gubernator, opa))

createTenantsYAML(t, e, dex.InternalEndpoint("https"), opa.InternalEndpoint("http"), getContainerName(t, tt, "observatorium_api"))
createTenantsYAML(t, e, dex.InternalEndpoint("https"), opa.InternalEndpoint("http"), getContainerName(e, "observatorium-api"))

token, err := obtainToken(dex.Endpoint("https"), getTLSClientConfig(t, e))
token, err := obtainToken(dex.Endpoint("https"), getContainerName(e, "dex"), getTLSClientConfig(t, e))
testutil.Ok(t, err)

return dex, token, gubernator.InternalEndpoint("grpc")
Expand Down
8 changes: 4 additions & 4 deletions test/e2e/tenants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import (
func TestTenantsRetryAuthenticationProviderRegistration(t *testing.T) {
t.Parallel()

e, err := e2e.New(e2e.WithName(envTenantsName))
e, err := e2e.New(e2e.WithName(uniqueE2ENetworkName(t)))
testutil.Ok(t, err)
t.Cleanup(e.Close)

prepareConfigsAndCerts(t, tenants, e)
dex, _, _ := startBaseServices(t, e, tenants)
prepareConfigsAndCerts(t, e)
dex, _, _ := startBaseServices(t, e)
readEndpoint, writeEndpoint, _ := startServicesForMetrics(t, e)

// Start API with stopped Dex and observe retries.
Expand Down Expand Up @@ -59,7 +59,7 @@ func TestTenantsRetryAuthenticationProviderRegistration(t *testing.T) {

// Restart Dex.
testutil.Ok(t, e2e.StartAndWaitReady(dex))
token, err := obtainToken(dex.Endpoint("https"), getTLSClientConfig(t, e))
token, err := obtainToken(dex.Endpoint("https"), getContainerName(e, "dex"), getTLSClientConfig(t, e))
testutil.Ok(t, err)

up, err := newUpRun(
Expand Down
Loading