feat: adjust sample to mvp #1
@@ -0,0 +1,17 @@
|
||||
name: Go Cache Key
|
||||
description: Create a cache key for Go dependencies
|
||||
|
||||
outputs:
|
||||
hash:
|
||||
description: The cache key for Go dependencies
|
||||
value: ${{ steps.hash-go.outputs.hash }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Create cache key
|
||||
shell: bash
|
||||
id: hash-go
|
||||
run: |
|
||||
echo "hash=$(sha256sum go.mod go.sum | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
||||
echo "hash=$hash" >> "$GITHUB_OUTPUT"
|
||||
+66
-20
@@ -8,30 +8,76 @@ env:
|
||||
RUNNER_TOOL_CACHE: /toolcache
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: test
|
||||
install-dependencies:
|
||||
name: install dependencies
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
|
||||
- name: Install dependencies
|
||||
uses: .gitea/workflows/install-go-dependencies
|
||||
|
||||
build-check:
|
||||
name: build check
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
needs: install-dependencies
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Run build script
|
||||
uses: .gitea/workflows/run-go-script
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- name: Create cache key
|
||||
id: hash-go
|
||||
run: echo "hash=$(sha256sum go.mod go.sum | sha256sum | cut -d' ' -f1)" >> "$GITHUB_OUTPUT"
|
||||
- name: cache go
|
||||
id: cache-go
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||
script: build
|
||||
|
||||
check-format:
|
||||
name: check format
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
needs: build-check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Run check format script
|
||||
uses: .gitea/workflows/run-go-script
|
||||
with:
|
||||
path: |
|
||||
/go_path
|
||||
/go_cache
|
||||
key: go_path-${{ steps.hash-go.outputs.hash }}
|
||||
restore-keys: |-
|
||||
go_cache-${{ steps.hash-go.outputs.hash }}
|
||||
- name: build
|
||||
run: make build
|
||||
script: check-format
|
||||
|
||||
check-lint:
|
||||
name: check lint
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
needs: build-check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Run check lint script
|
||||
uses: .gitea/workflows/run-go-script
|
||||
with:
|
||||
script: check-lint
|
||||
|
||||
test:
|
||||
name: test
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
needs: build-check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Run test script
|
||||
uses: .gitea/workflows/run-go-script
|
||||
with:
|
||||
script: test
|
||||
|
||||
image-check:
|
||||
name: image check
|
||||
runs-on:
|
||||
- ubuntu-latest
|
||||
- linux_amd64
|
||||
needs: build-check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Build image
|
||||
run: make build-image
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
name: Install Go Dependencies
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
install-dependencies:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0.4.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- name: Create cache key
|
||||
uses: .gitea/actions/go-cache-key@main
|
||||
- name: cache go
|
||||
id: cache-go
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
/go_path
|
||||
/go_cache
|
||||
key: go_path-${{ steps.hash-go.outputs.hash }}
|
||||
restore-keys: |-
|
||||
go_cache-${{ steps.hash-go.outputs.hash }}
|
||||
@@ -0,0 +1,35 @@
|
||||
name: Run Go Script
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
script:
|
||||
description: The script to run
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
run-script:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
- name: Setup go
|
||||
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- name: Create cache key
|
||||
uses: .gitea/actions/go-cache-key@main
|
||||
- name: Install dependencies from Cache
|
||||
id: cache-go
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
/go_path
|
||||
/go_cache
|
||||
key: go_path-${{ steps.hash-go.outputs.hash }}
|
||||
restore-keys: |-
|
||||
go_cache-${{ steps.hash-go.outputs.hash }}
|
||||
- name: Run script
|
||||
run: make ${{ inputs.script }}
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
lcov.info
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
@@ -2,14 +2,39 @@ ifneq (,$(wildcard ./.env))
|
||||
include .env
|
||||
export
|
||||
endif
|
||||
.PHONY: build run codegen
|
||||
.PHONY: build run codegen build-image test test-unit test-coverage lint format check-format
|
||||
|
||||
build:
|
||||
go build -o main
|
||||
|
||||
build-image:
|
||||
docker build -t authentik-kubernetes-operator:latest .
|
||||
|
||||
run:
|
||||
make build
|
||||
./main --kubeconfig=/home/tbehrendt/.kube/config
|
||||
|
||||
codegen:
|
||||
./scripts/codegen.sh
|
||||
|
||||
test: test-unit test-coverage
|
||||
|
||||
test-unit:
|
||||
go test . -coverprofile=coverage.out
|
||||
|
||||
test-coverage:
|
||||
go tool gcov2lcov -infile coverage.out > lcov.info
|
||||
|
||||
lint:
|
||||
go vet ./...
|
||||
|
||||
format:
|
||||
gofmt -w .
|
||||
|
||||
check-format:
|
||||
@OUTPUT=$$(gofmt -l .); \
|
||||
if [ -n "$$OUTPUT" ]; then \
|
||||
echo "Formatter failed for:"; \
|
||||
echo "$$OUTPUT"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
+8
-7
@@ -210,7 +210,7 @@ func (c *Controller) reconcileDelete(ctx context.Context, pp *v1alpha1.ProxyProv
|
||||
r, err := c.authentik.ProvidersApi.ProvidersProxyDestroy(ctx, int32(pk)).Execute()
|
||||
if err != nil {
|
||||
// This handles an edge-case, where when the ProxyProvider on Authentik has already been deleted, but the finalizer is still present. We just remove the finalizer and return.
|
||||
if r.StatusCode != http.StatusNotFound {
|
||||
if r != nil && r.StatusCode != http.StatusNotFound {
|
||||
return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyDestroy`: %w with response %v", err, r)
|
||||
}
|
||||
}
|
||||
@@ -226,13 +226,14 @@ func (c *Controller) reconcileUpdate(ctx context.Context, pp *v1alpha1.ProxyProv
|
||||
return fmt.Errorf("error parsing PK: %v", err)
|
||||
}
|
||||
_, r, err := c.authentik.ProvidersApi.ProvidersAllRetrieve(ctx, int32(pk)).Execute()
|
||||
if err != nil && r.StatusCode != http.StatusNotFound {
|
||||
|
||||
if err != nil {
|
||||
if r != nil && r.StatusCode == http.StatusNotFound {
|
||||
// This handles an edge-case, where when the PorxyProvider on Authentik has been deleted, e.g. by mistake. We just remove the PK and return.
|
||||
// During the next reconciliation, the ProxyProvider will be re-created.
|
||||
pp.Status.PK = ""
|
||||
return c.updateProxyProviderStatus(ctx, pp)
|
||||
}
|
||||
return fmt.Errorf("error retrieving existing ProxyProvider: %v with response %v", err, r)
|
||||
} else if r.StatusCode == http.StatusNotFound {
|
||||
// This handles an edge-case, where when the PorxyProvider on Authentik has been deleted, e.g. by mistake. We just remove the PK and return.
|
||||
// During the next reconciliation, the ProxyProvider will be re-created.
|
||||
pp.Status.PK = ""
|
||||
}
|
||||
|
||||
proxyProviderRequest := &authentikapi.PatchedProxyProviderRequest{
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
// AI generated tests and not yet reviewed.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
|
||||
operatorfake "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/fake"
|
||||
operatorinformers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions"
|
||||
authentikapi "goauthentik.io/api/v3"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
func TestController_syncHandler_create(t *testing.T) {
|
||||
const wantPK = 42
|
||||
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{
|
||||
proxyCreate: func(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(t, w, http.StatusCreated, map[string]any{"pk": wantPK})
|
||||
},
|
||||
})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, testProxyProvider(), server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: "default", Name: "test-pp"})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v", err)
|
||||
}
|
||||
|
||||
got := getProxyProvider(t, ctrl, "default", "test-pp")
|
||||
if got.Status.PK != "42" {
|
||||
t.Fatalf("status.pk = %q, want 42", got.Status.PK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_ensureFinalizers(t *testing.T) {
|
||||
pp := testProxyProvider()
|
||||
pp.Status.PK = "42"
|
||||
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, pp, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pp.Namespace, Name: pp.Name})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v", err)
|
||||
}
|
||||
|
||||
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
|
||||
if !slices.Contains(got.Finalizers, DeleteAuthentikProxyProviderFinalizer) {
|
||||
t.Fatalf("finalizers = %v, want %q", got.Finalizers, DeleteAuthentikProxyProviderFinalizer)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_update(t *testing.T) {
|
||||
pp := testProxyProvider()
|
||||
pp.Status.PK = "42"
|
||||
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
|
||||
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{
|
||||
allRetrieve: func(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42})
|
||||
},
|
||||
proxyPartialUpdate: func(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42})
|
||||
},
|
||||
})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, pp, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pp.Namespace, Name: pp.Name})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v", err)
|
||||
}
|
||||
|
||||
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
|
||||
if got.Status.PK != "42" {
|
||||
t.Fatalf("status.pk = %q, want 42", got.Status.PK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_update_providerNotFound(t *testing.T) {
|
||||
pp := testProxyProvider()
|
||||
pp.Status.PK = "42"
|
||||
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
|
||||
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{
|
||||
allRetrieve: func(w http.ResponseWriter, _ *http.Request) {
|
||||
http.NotFound(w, nil)
|
||||
},
|
||||
})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, pp, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pp.Namespace, Name: pp.Name})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v", err)
|
||||
}
|
||||
|
||||
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
|
||||
if got.Status.PK != "" {
|
||||
t.Fatalf("status.pk = %q, want empty after provider not found", got.Status.PK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_delete(t *testing.T) {
|
||||
now := metav1.Now()
|
||||
pp := testProxyProvider()
|
||||
pp.Status.PK = "42"
|
||||
pp.DeletionTimestamp = &now
|
||||
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
|
||||
|
||||
var destroyCalled bool
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{
|
||||
proxyDestroy: func(w http.ResponseWriter, r *http.Request) {
|
||||
destroyCalled = true
|
||||
if r.Method != http.MethodDelete {
|
||||
t.Errorf("destroy method = %s, want DELETE", r.Method)
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
},
|
||||
})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, pp, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pp.Namespace, Name: pp.Name})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v", err)
|
||||
}
|
||||
if !destroyCalled {
|
||||
t.Fatal("expected Authentik destroy call")
|
||||
}
|
||||
|
||||
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
|
||||
if slices.Contains(got.Finalizers, DeleteAuthentikProxyProviderFinalizer) {
|
||||
t.Fatalf("finalizers = %v, want finalizer removed", got.Finalizers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_delete_providerAlreadyGone(t *testing.T) {
|
||||
now := metav1.Now()
|
||||
pp := testProxyProvider()
|
||||
pp.Status.PK = "42"
|
||||
pp.DeletionTimestamp = &now
|
||||
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
|
||||
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{
|
||||
proxyDestroy: func(w http.ResponseWriter, _ *http.Request) {
|
||||
http.NotFound(w, nil)
|
||||
},
|
||||
})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, pp, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pp.Namespace, Name: pp.Name})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v", err)
|
||||
}
|
||||
|
||||
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
|
||||
if slices.Contains(got.Finalizers, DeleteAuthentikProxyProviderFinalizer) {
|
||||
t.Fatalf("finalizers = %v, want finalizer removed after 404", got.Finalizers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_notFound(t *testing.T) {
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, nil, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: "default", Name: "missing"})
|
||||
if err != nil {
|
||||
t.Fatalf("syncHandler() error = %v, want nil for missing object", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_syncHandler_invalidPK(t *testing.T) {
|
||||
pp := testProxyProvider()
|
||||
pp.Status.PK = "not-a-number"
|
||||
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
|
||||
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, ctx, cancel := newTestController(t, pp, server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pp.Namespace, Name: pp.Name})
|
||||
if err == nil {
|
||||
t.Fatal("syncHandler() error = nil, want parse error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "error parsing PK") {
|
||||
t.Fatalf("syncHandler() error = %v, want PK parse error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestController_enqueueProxyProvider(t *testing.T) {
|
||||
server := newAuthentikTestServer(t, authentikTestHandlers{})
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
ctrl, _, cancel := newTestController(t, testProxyProvider(), server.URL)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
ctrl.enqueueProxyProvider(testProxyProvider())
|
||||
|
||||
if ctrl.workqueue.Len() != 1 {
|
||||
t.Fatalf("workqueue length = %d, want 1", ctrl.workqueue.Len())
|
||||
}
|
||||
}
|
||||
|
||||
// --- test helpers ---
|
||||
|
||||
func testProxyProvider() *v1alpha1.ProxyProvider {
|
||||
return &v1alpha1.ProxyProvider{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: v1alpha1.SchemeGroupVersion.String(),
|
||||
Kind: "ProxyProvider",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-pp",
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v1alpha1.ProxyProviderSpec{
|
||||
Name: "my-app",
|
||||
AuthorizationFlow: "flow-auth",
|
||||
InvalidationFlow: "flow-invalidate",
|
||||
ExternalHost: "https://app.example.com",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newTestController(t *testing.T, pp *v1alpha1.ProxyProvider, authentikURL string) (*Controller, context.Context, context.CancelFunc) {
|
||||
t.Helper()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
ctrl, _, stop := newTestControllerWithContext(t, ctx, pp, authentikURL)
|
||||
return ctrl, ctx, func() {
|
||||
cancel()
|
||||
stop()
|
||||
}
|
||||
}
|
||||
|
||||
func newTestControllerWithContext(t *testing.T, ctx context.Context, pp *v1alpha1.ProxyProvider, authentikURL string) (*Controller, context.Context, func()) {
|
||||
t.Helper()
|
||||
|
||||
authentikClient := newAuthentikAPIClientForTest(t, authentikURL)
|
||||
|
||||
var objects []runtime.Object
|
||||
if pp != nil {
|
||||
objects = append(objects, pp)
|
||||
}
|
||||
proxyClient := operatorfake.NewSimpleClientset(objects...)
|
||||
|
||||
informerFactory := operatorinformers.NewSharedInformerFactory(proxyClient, 0)
|
||||
proxyInformer := informerFactory.Proxyprovider().V1alpha1().ProxyProviders()
|
||||
|
||||
ctrl := NewController(ctx, fake.NewClientset(), proxyClient, authentikClient, proxyInformer)
|
||||
|
||||
informerFactory.Start(ctx.Done())
|
||||
for informerType, synced := range informerFactory.WaitForCacheSync(ctx.Done()) {
|
||||
if !synced {
|
||||
t.Fatalf("informer %v failed to sync", informerType)
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl, ctx, func() {}
|
||||
}
|
||||
|
||||
func newAuthentikAPIClientForTest(t *testing.T, serverURL string) *authentikapi.APIClient {
|
||||
t.Helper()
|
||||
|
||||
u, err := url.Parse(serverURL)
|
||||
if err != nil {
|
||||
t.Fatalf("parse server URL: %v", err)
|
||||
}
|
||||
|
||||
cfg := authentikapi.NewConfiguration()
|
||||
cfg.Scheme = u.Scheme
|
||||
cfg.Host = u.Host
|
||||
|
||||
return authentikapi.NewAPIClient(cfg)
|
||||
}
|
||||
|
||||
type authentikTestHandlers struct {
|
||||
proxyCreate http.HandlerFunc
|
||||
proxyDestroy http.HandlerFunc
|
||||
proxyPartialUpdate http.HandlerFunc
|
||||
allRetrieve http.HandlerFunc
|
||||
}
|
||||
|
||||
func newAuthentikTestServer(t *testing.T, handlers authentikTestHandlers) *httptest.Server {
|
||||
t.Helper()
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Path
|
||||
|
||||
switch {
|
||||
case path == "/api/v3/providers/proxy/" && r.Method == http.MethodPost:
|
||||
if handlers.proxyCreate != nil {
|
||||
handlers.proxyCreate(w, r)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
|
||||
case strings.HasPrefix(path, "/api/v3/providers/proxy/") && strings.HasSuffix(path, "/"):
|
||||
idPath := strings.TrimPrefix(path, "/api/v3/providers/proxy/")
|
||||
if idPath == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
switch r.Method {
|
||||
case http.MethodDelete:
|
||||
if handlers.proxyDestroy != nil {
|
||||
handlers.proxyDestroy(w, r)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
case http.MethodPatch:
|
||||
if handlers.proxyPartialUpdate != nil {
|
||||
handlers.proxyPartialUpdate(w, r)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
default:
|
||||
http.Error(w, "unexpected method on proxy instance", http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
case strings.HasPrefix(path, "/api/v3/providers/all/") && strings.HasSuffix(path, "/"):
|
||||
if r.Method == http.MethodGet && handlers.allRetrieve != nil {
|
||||
handlers.allRetrieve(w, r)
|
||||
return
|
||||
}
|
||||
http.NotFound(w, r)
|
||||
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
})
|
||||
|
||||
return httptest.NewServer(handler)
|
||||
}
|
||||
|
||||
func writeJSON(t *testing.T, w http.ResponseWriter, status int, body any) {
|
||||
t.Helper()
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||
t.Fatalf("write JSON response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func getProxyProvider(t *testing.T, ctrl *Controller, namespace, name string) *v1alpha1.ProxyProvider {
|
||||
t.Helper()
|
||||
|
||||
got, err := ctrl.proxyProviderClientset.ProxyproviderV1alpha1().ProxyProviders(namespace).Get(
|
||||
context.Background(), name, metav1.GetOptions{},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("get ProxyProvider: %v", err)
|
||||
}
|
||||
return got
|
||||
}
|
||||
@@ -36,6 +36,7 @@ require (
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
|
||||
github.com/google/gnostic-models v0.7.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jandelgado/gcov2lcov v1.1.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||
@@ -60,3 +61,5 @@ require (
|
||||
)
|
||||
|
||||
replace k8s.io/code-generator => ./code-generator
|
||||
|
||||
tool github.com/jandelgado/gcov2lcov
|
||||
|
||||
@@ -49,6 +49,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jandelgado/gcov2lcov v1.1.1 h1:CHUNoAglvb34DqmMoZchnzDbA3yjpzT8EoUvVqcAY+s=
|
||||
github.com/jandelgado/gcov2lcov v1.1.1/go.mod h1:tMVUlMVtS1po2SB8UkADWhOT5Y5Q13XOce2AYU69JuI=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
@@ -71,9 +73,16 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
|
||||
github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
@@ -107,6 +116,7 @@ gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnf
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.0.0-20260509204538-0dfb117cc6ec h1:xf12Yh3ltN4fnNyP0CyyM0TwNVnZDfLJjV3+bf9fPFY=
|
||||
|
||||
Reference in New Issue
Block a user