Skip to content
Merged
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
1 change: 0 additions & 1 deletion e2e/embedded_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
Expand Down
3 changes: 2 additions & 1 deletion e2e/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strings"
"time"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/samber/lo"
Expand All @@ -29,6 +28,8 @@ import (
"k8s.io/client-go/tools/clientcmd"
"k8s.io/utils/pointer"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"

"github.com/authzed/spicedb-kubeapi-proxy/pkg/authz/distributedtx"
"github.com/authzed/spicedb-kubeapi-proxy/pkg/config/proxyrule"
"github.com/authzed/spicedb-kubeapi-proxy/pkg/failpoints"
Expand Down
5 changes: 3 additions & 2 deletions e2e/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"os"
goruntime "runtime"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
"github.com/authzed/spicedb/pkg/tuple"
"github.com/go-logr/logr"
. "github.com/onsi/gomega"
"github.com/samber/lo"
Expand All @@ -20,6 +18,9 @@ import (
"sigs.k8s.io/controller-runtime/tools/setup-envtest/store"
"sigs.k8s.io/controller-runtime/tools/setup-envtest/versions"
"sigs.k8s.io/controller-runtime/tools/setup-envtest/workflows"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
"github.com/authzed/spicedb/pkg/tuple"
)

// GetAllTuples collects all tuples matching the filter from SpiceDB
Expand Down
17 changes: 13 additions & 4 deletions magefiles/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,19 @@ func (t Test) All() error {

// Unit runs the unit tests.
func (t Test) Unit() error {
// TODO add -race
args := []string{"test", "-count=1"}
args = append(args, []string{"-coverpkg=./...", "-covermode=atomic", "-coverprofile=coverageunit.txt"}...)
args = append(args, "./...")
args := []string{
"test",
// bypass cache
"-count=1",
// check for data races
"-race",
// coverage flags
"-coverpkg=./...",
"-covermode=atomic",
"-coverprofile=coverageunit.txt",
// package
"./...",
}
return RunSh("go", WithV())(args...)
}

Expand Down
1 change: 0 additions & 1 deletion magefiles/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/onsi/gomega/gexec"
"golang.org/x/exp/slices"
"sigs.k8s.io/kind/pkg/apis/config/v1alpha4"

kind "sigs.k8s.io/kind/pkg/cluster"
"sigs.k8s.io/kind/pkg/cluster/nodeutils"
"sigs.k8s.io/kind/pkg/cmd"
Expand Down
7 changes: 4 additions & 3 deletions pkg/proxy/authn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import (
)

func TestRequestHeaderAuth(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

userInfo := runProxyRequest(t, ctx, map[string][]string{
Expand Down Expand Up @@ -96,6 +96,7 @@ func runProxyRequest(t testing.TB, ctx context.Context, headers map[string][]str
}

opts := NewOptions(WithEmbeddedSpiceDBEndpoint)
opts.SkipLoggerSetupForTesting = true
opts.RestConfigFunc = func() (*rest.Config, http.RoundTripper, error) {
ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
Expand Down Expand Up @@ -184,15 +185,15 @@ func runProxyRequest(t testing.TB, ctx context.Context, headers map[string][]str
return rules.NewResolveInputFromHttp(req)
})

c, err := opts.Complete(t.Context())
c, err := opts.Complete(testContext(t))
require.NoError(t, err)
require.NotNil(t, c)

proxySrv, err := NewServer(ctx, c)
require.NoError(t, err)

// Start the server in a separate context that won't be cancelled until we're done
serverCtx, serverCancel := context.WithCancel(t.Context())
serverCtx, serverCancel := context.WithCancel(testContext(t))
t.Cleanup(serverCancel)

serverReady := make(chan struct{})
Expand Down
43 changes: 24 additions & 19 deletions pkg/proxy/embedded_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,30 @@ import (
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/endpoints/request"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
logsv1 "k8s.io/component-base/logs/api/v1"
"k8s.io/klog/v2"
"k8s.io/klog/v2/ktesting"

"github.com/authzed/spicedb-kubeapi-proxy/pkg/rules"
)

// testContext returns a context whose klog logger writes to t.Log. Proxy and
// embedded-SpiceDB output is then captured per-test by the testing framework and
// only printed when the test fails (or under -v), so successful runs are quiet.
//
// The logger is injected via the context rather than klog.SetLogger so that it
// never mutates klog's global logger; mutating that global races with background
// server goroutines from earlier tests under -race (which is why the options keep
// SkipLoggerSetupForTesting set).
func testContext(t testing.TB) context.Context {
t.Helper()
logger := ktesting.NewLogger(t, ktesting.NewConfig(ktesting.Verbosity(3)))
return klog.NewContext(t.Context(), logger)
}

func TestEmbeddedMode(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))
ctx := t.Context()
ctx := testContext(t)

opts := createEmbeddedTestOptions(t)
completedConfig, err := opts.Complete(ctx)
Expand Down Expand Up @@ -69,9 +82,7 @@ func TestEmbeddedMode(t *testing.T) {
}

func TestEmbeddedModeCustomHeaders(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))
Comment thread
ecordell marked this conversation as resolved.

ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

// Create a proxy with custom header names
Expand Down Expand Up @@ -112,9 +123,7 @@ func TestEmbeddedModeCustomHeaders(t *testing.T) {
}

func TestEmbeddedModeAuthenticationConfiguration(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

// Create one proxy with multiple header configuration for all tests
Expand Down Expand Up @@ -196,14 +205,13 @@ func TestEmbeddedModeAuthenticationConfiguration(t *testing.T) {
}

func TestEmbeddedModeDefaults(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

// Create embedded proxy with no explicit header configuration to test defaults
opts := NewOptions(WithEmbeddedProxy, WithEmbeddedSpiceDBEndpoint)
opts.Authentication.Embedded.Enabled = true
opts.SkipLoggerSetupForTesting = true

// Configure mock upstream server
opts.RestConfigFunc = func() (*rest.Config, http.RoundTripper, error) {
Expand Down Expand Up @@ -259,9 +267,7 @@ func TestEmbeddedModeDefaults(t *testing.T) {
}

func TestEmbeddedClientFunctionalOptions(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

// Create one proxy server for all subtests to avoid logging config issues
Expand Down Expand Up @@ -350,9 +356,7 @@ func TestEmbeddedClientFunctionalOptions(t *testing.T) {
}

func TestEmbeddedClientCustomHeaderConfig(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

// Create proxy with custom header names
Expand Down Expand Up @@ -402,6 +406,7 @@ func createEmbeddedTestOptions(t *testing.T) *Options {

opts := NewOptions(WithEmbeddedProxy, WithEmbeddedSpiceDBEndpoint)
opts.Authentication.Embedded.Enabled = true
opts.SkipLoggerSetupForTesting = true

// Configure mock upstream server
opts.RestConfigFunc = func() (*rest.Config, http.RoundTripper, error) {
Expand Down
34 changes: 13 additions & 21 deletions pkg/proxy/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import (
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"k8s.io/apiserver/pkg/endpoints/request"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/tools/clientcmd"
logsv1 "k8s.io/component-base/logs/api/v1"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
"github.com/authzed/grpcutil"
Expand All @@ -24,34 +22,29 @@ import (
)

func TestKubeConfig(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

opts := optionsForTesting(t, WithEmbeddedSpiceDBEndpoint)
require.Empty(t, opts.Validate())

c, err := opts.Complete(t.Context())
c, err := opts.Complete(testContext(t))
require.NoError(t, err)
require.NotNil(t, c)

require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))
opts = optionsForTesting(t)
opts.BackendKubeconfigPath = uuid.NewString()

c, err = opts.Complete(t.Context())
c, err = opts.Complete(testContext(t))
require.ErrorContains(t, err, "couldn't load kubeconfig")
require.ErrorContains(t, err, opts.BackendKubeconfigPath)
require.Nil(t, c, "expected nil config on error")
}

func TestInClusterConfig(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

opts := optionsForTesting(t, WithEmbeddedSpiceDBEndpoint)
opts.BackendKubeconfigPath = ""
opts.UseInClusterConfig = true
require.Empty(t, opts.Validate())

c, err := opts.Complete(t.Context())
c, err := opts.Complete(testContext(t))
require.NoError(t, err)
require.NotNil(t, c)
require.NotNil(t, opts.RestConfigFunc, "missing kube client REST config")
Expand All @@ -64,7 +57,7 @@ func TestEmbeddedSpiceDB(t *testing.T) {
opts := optionsForTesting(t, WithEmbeddedSpiceDBEndpoint)
require.Empty(t, opts.Validate())

c, err := opts.Complete(t.Context())
c, err := opts.Complete(testContext(t))
require.NoError(t, err)
require.NotNil(t, c)

Expand All @@ -74,7 +67,7 @@ func TestEmbeddedSpiceDB(t *testing.T) {
}

func TestRemoteSpiceDB(t *testing.T) {
ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
defer cancel()

srv, addr := newTCPSpiceDB(t, ctx)
Expand All @@ -90,7 +83,7 @@ func TestRemoteSpiceDB(t *testing.T) {
opts.SpiceDBOptions.SecureSpiceDBTokensBySpace = "foobar"
require.Empty(t, opts.Validate())

c, err := opts.Complete(t.Context())
c, err := opts.Complete(testContext(t))
require.NoError(t, err)
require.NotNil(t, c)

Expand All @@ -109,15 +102,15 @@ func TestRemoteSpiceDBCerts(t *testing.T) {
opts.SpiceDBOptions.SpicedbCAPath = "test"
require.Empty(t, opts.Validate())

_, err := opts.Complete(t.Context())
_, err := opts.Complete(testContext(t))
require.ErrorContains(t, err, "unable to load custom certificates")
}

func TestRuleConfig(t *testing.T) {
opts := optionsForTesting(t, WithEmbeddedSpiceDBEndpoint)
require.Empty(t, opts.Validate())

c, err := opts.Complete(t.Context())
c, err := opts.Complete(testContext(t))
require.NoError(t, err)
require.NotNil(t, c)

Expand All @@ -132,7 +125,6 @@ func TestRuleConfig(t *testing.T) {
require.Empty(t, rules[0].Checks)
require.Nil(t, rules[0].Update)

require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))
errConfigBytes := []byte(`
apiVersion: authzed.com/v1alpha1
kind: ProxyRule
Expand All @@ -152,15 +144,17 @@ prefilter:
opts.RuleConfigFile = errConfigFile
require.Empty(t, opts.Validate())

_, err = opts.Complete(t.Context())
_, err = opts.Complete(testContext(t))
require.ErrorContains(t, err, "expected")
}

func optionsForTesting(t *testing.T, opts ...setOpt) *Options {
t.Helper()

require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))
options := NewOptions(opts...)
// Without this option, you get data races as the different tests
// touch the k8s logger at the same time.
options.SkipLoggerSetupForTesting = true
options.SecureServing.BindPort = getFreePort(t, "127.0.0.1")
options.SecureServing.BindAddress = net.ParseIP("127.0.0.1")
options.BackendKubeconfigPath = kubeConfigForTest(t)
Expand Down Expand Up @@ -216,9 +210,7 @@ relationships: |
}

func TestWithEmbeddedSpiceDBBootstrapIntegration(t *testing.T) {
defer require.NoError(t, logsv1.ResetForTest(utilfeature.DefaultFeatureGate))

ctx, cancel := context.WithCancel(t.Context())
ctx, cancel := context.WithCancel(testContext(t))
t.Cleanup(cancel)

// Create custom bootstrap content
Expand Down
Loading