Compare commits

...

4 Commits

Author SHA1 Message Date
renovate-bot 23b2ad1505 chore(deps): update k8s.io/kube-openapi digest to aa012df
renovate/stability-days Updates have met minimum release age requirement
CI / install-dependencies (pull_request) Successful in 16s
CI / image check (pull_request) Successful in 1m0s
CI / check format (pull_request) Successful in 48s
CI / build check (pull_request) Successful in 1m7s
CI / test (pull_request) Successful in 52s
CI / check lint (pull_request) Successful in 7m23s
2026-05-28 10:01:30 +00:00
renovate-bot fd75e6314e chore(deps): update kubernetes packages to v0.36.1 (#9)
CD / Create tag (push) Successful in 24s
CD / Build and push (amd64) (push) Successful in 1m33s
CD / Create manifest (push) Successful in 7s
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [k8s.io/api](https://github.com/kubernetes/api) | `v0.36.0` → `v0.36.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/k8s.io%2fapi/v0.36.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/k8s.io%2fapi/v0.36.0/v0.36.1?slim=true) |
| [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `v0.36.0` → `v0.36.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/k8s.io%2fapimachinery/v0.36.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/k8s.io%2fapimachinery/v0.36.0/v0.36.1?slim=true) |
| [k8s.io/client-go](https://github.com/kubernetes/client-go) | `v0.36.0` → `v0.36.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/k8s.io%2fclient-go/v0.36.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/k8s.io%2fclient-go/v0.36.0/v0.36.1?slim=true) |

---

### Release Notes

<details>
<summary>kubernetes/api (k8s.io/api)</summary>

### [`v0.36.1`](https://github.com/kubernetes/api/compare/v0.36.0...v0.36.1)

[Compare Source](https://github.com/kubernetes/api/compare/v0.36.0...v0.36.1)

</details>

<details>
<summary>kubernetes/apimachinery (k8s.io/apimachinery)</summary>

### [`v0.36.1`](https://github.com/kubernetes/apimachinery/compare/v0.36.0...v0.36.1)

[Compare Source](https://github.com/kubernetes/apimachinery/compare/v0.36.0...v0.36.1)

</details>

<details>
<summary>kubernetes/client-go (k8s.io/client-go)</summary>

### [`v0.36.1`](https://github.com/kubernetes/client-go/compare/v0.36.0...v0.36.1)

[Compare Source](https://github.com/kubernetes/client-go/compare/v0.36.0...v0.36.1)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41LjQiLCJ1cGRhdGVkSW5WZXIiOiI0My41LjQiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Reviewed-on: #9
Reviewed-by: t.behrendt <t.behrendt@noreply.localhost>
Co-authored-by: Renovate Bot <renovate@t00n.de>
Co-committed-by: Renovate Bot <renovate@t00n.de>
2026-05-25 18:54:40 +02:00
t.behrendt 26bd576690 feat: vertical slice application -> provider -> binding (#4)
CD / Create tag (push) Successful in 11s
CD / Build and push (amd64) (push) Successful in 1m32s
CD / Create manifest (push) Successful in 7s
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
2026-05-25 17:14:35 +02:00
t.behrendt 2a091df8b9 ci: fix Makefile test (#10)
CD / Build and push (amd64) (push) Successful in 1m31s
CD / Create tag (push) Successful in 12s
CD / Create manifest (push) Successful in 19s
Reviewed-on: #10
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
2026-05-25 13:21:26 +02:00
68 changed files with 4925 additions and 126 deletions
+1
View File
@@ -1,6 +1,7 @@
*
!pkg
!internal
!controller.go
!main.go
!go.mod
+1 -1
View File
@@ -20,7 +20,7 @@ codegen:
test: test-unit test-coverage
test-unit:
go test . -coverprofile=coverage.out
go test ./... -coverprofile=coverage.out
test-coverage:
go tool gcov2lcov -infile coverage.out > lcov.info
+43 -1
View File
@@ -11,6 +11,8 @@ Manual changes to the resources in Authentik will be overwritten by the operator
| Custom Resource | CRD File | Short Name |
| --------------- | ---------------------------------------------------------- | ---------- |
| ProxyProvider | [`proxyProvider.yaml`](`artifacts/crd/proxyProvider.yaml`) | pp |
| Application | [`application.yaml`](`artifacts/crd/application.yaml`) | app |
| PolicyBinding | [`policyBinding.yaml`](`artifacts/crd/policyBinding.yaml`) | pb |
### ProxyProvider
@@ -32,9 +34,49 @@ spec:
invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184
# The external host of your application.
external_host: https://example.t00n.de
# The ID of the outpost, which at current point in time can only be retrieved from Authentik directly. In this example: "Proxy-Forward-Auth-Auto"
outpost: e004ffe7-4af6-4ac1-9e9d-522354799e1f
```
The ProxyProvider will be created in Authentik, but will not be assigned to an outpost or an application (Resources are TBD).
The ProxyProvider will be created in Authentik and assigned to the configured outpost.
### Application
The Application only supports a reduced set of fields.
Example [`application.yaml`](`artifacts/examples/application.yaml`):
```yaml
apiVersion: application.t000-n.de/v1alpha1
kind: Application
metadata:
name: application-example
spec:
name: Application Example
slug: application-example
# The ID of the provider, which can be retrieved from e.g. the ProxyPRovider via "kubectl get pp proxy-provider-example -o jsonpath='{.status.pk}'"
provider: 105
```
### PolicyBinding
The PolicyBinding is used to bind a policy to a target, e.g. allow a group or user to access an application.
The PolicyBinding only supports a reduced set of fields.
Example [`policyBinding.yaml`](`artifacts/examples/policyBinding.yaml`):
```yaml
apiVersion: policybinding.t000-n.de/v1alpha1
kind: PolicyBinding
metadata:
name: policy-binding-example
spec:
group: 14ab813f-a7f9-481b-9b08-781953ae9ebf
# The ID of the target, e.g. an Application, which can be retrieved from e.g. the Application via "kubectl get app application-example -o jsonpath='{.status.pk}'"
target: 8dd85627-9c48-49c2-8afc-d73dd122ffc2
# The order in which the policy is applied. This needs to be unique for each PolicyBinding.
order: 1
```
## Versioning
+56
View File
@@ -0,0 +1,56 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: applications.application.t000-n.de
spec:
group: application.t000-n.de
versions:
- name: v1alpha1
served: true
storage: true
subresources:
status: {}
additionalPrinterColumns:
- name: PK
type: string
jsonPath: .status.pk
- name: Name
type: string
jsonPath: .spec.name
- name: Slug
type: string
jsonPath: .spec.slug
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
name:
type: string
description: Application's display name
slug:
type: string
description: Internal application name, used in URLs.
pattern: ^[-a-zA-Z0-9_]+$
provider:
type: integer
format: int32
required:
- name
- slug
status:
type: object
properties:
pk:
type: string
format: uuid
required:
- pk
names:
kind: Application
plural: applications
shortNames:
- app
scope: Namespaced
+53
View File
@@ -0,0 +1,53 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: policybindings.policybinding.t000-n.de
spec:
group: policybinding.t000-n.de
versions:
- name: v1alpha1
served: true
storage: true
subresources:
status: {}
additionalPrinterColumns:
- name: PK
type: string
jsonPath: .status.pk
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
policy:
type: string
format: uuid
group:
type: string
format: uuid
user:
type: integer
format: int32
target:
type: string
format: uuid
order:
type: integer
required:
- target
- order
status:
type: object
properties:
pk:
type: string
required:
- pk
names:
kind: PolicyBinding
plural: policybindings
shortNames:
- pb
scope: Namespaced
+7
View File
@@ -16,6 +16,9 @@ spec:
- name: PK
type: string
jsonPath: .status.pk
- name: Outpost
type: string
jsonPath: .spec.outpost
schema:
openAPIV3Schema:
type: object
@@ -31,11 +34,15 @@ spec:
type: string
external_host:
type: string
outpost:
type: string
format: uuid
required:
- name
- authorization_flow
- invalidation_flow
- external_host
- outpost
status:
type: object
properties:
+8
View File
@@ -0,0 +1,8 @@
apiVersion: application.t000-n.de/v1alpha1
kind: Application
metadata:
name: application-example
spec:
name: Application Example
slug: application-example
provider: 105
+8
View File
@@ -0,0 +1,8 @@
apiVersion: policybinding.t000-n.de/v1alpha1
kind: PolicyBinding
metadata:
name: policy-binding-example
spec:
group: 14ab813f-a7f9-481b-9b08-781953ae9ebf
target: 8dd85627-9c48-49c2-8afc-d73dd122ffc2
order: 1
+1
View File
@@ -9,3 +9,4 @@ spec:
authorization_flow: 16896c6d-b326-42d1-8d3f-93f32921962e
invalidation_flow: 7acac1ef-19e3-4a6f-8d8d-14ca7031d184
external_host: https://example.t00n.de
outpost: ce8f74c0-88cd-47fe-96f5-d6507b739ceb
+4 -4
View File
@@ -7,11 +7,11 @@ godebug default=go1.26
require (
goauthentik.io/api/v3 v3.2026020.16
golang.org/x/time v0.15.0
k8s.io/api v0.36.0
k8s.io/apimachinery v0.36.0
k8s.io/client-go v0.36.0
k8s.io/api v0.36.1
k8s.io/apimachinery v0.36.1
k8s.io/client-go v0.36.1
k8s.io/klog/v2 v2.140.0
k8s.io/kube-openapi v0.0.0-20260511211612-da4e56fe5676
k8s.io/kube-openapi v0.0.0-20260520065146-aa012df4f4af
sigs.k8s.io/structured-merge-diff/v6 v6.4.0
)
+8
View File
@@ -123,18 +123,26 @@ k8s.io/api v0.0.0-20260509204538-0dfb117cc6ec h1:xf12Yh3ltN4fnNyP0CyyM0TwNVnZDfL
k8s.io/api v0.0.0-20260509204538-0dfb117cc6ec/go.mod h1:C+fcNlNQ9TcKHspN+DD7UybdfnjDAGyBjfCd6W7ogbY=
k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80=
k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34=
k8s.io/api v0.36.1 h1:XbL/EMj8K2aJpJtePmqUyQMsM0D4QI2pvl7YKJ20FTY=
k8s.io/api v0.36.1/go.mod h1:KOWo4ey3TINlXjeHVuwB3i+tXXnu+UcwFBHlI/9dvEo=
k8s.io/apimachinery v0.0.0-20260513183604-f9371b815e42 h1:rWdGOTor3z0WSyZcRl9ms4dn9Cw9CqmNBqXuf2z0k1k=
k8s.io/apimachinery v0.0.0-20260513183604-f9371b815e42/go.mod h1:hiubQ6UTHIdr0bS8ExXOJEywFVOoudnldm/l/NiNVlA=
k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ=
k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc=
k8s.io/apimachinery v0.36.1 h1:G63Gjx2W+q0YD+72Vo8oY0nDnePVwnuzTmmy5ENrVSA=
k8s.io/apimachinery v0.36.1/go.mod h1:ibYOR00vW/I1kzvi5SF0dRuJ52BvKtfvRdOn35GPQ+8=
k8s.io/client-go v0.0.0-20260509205101-ca52b81a2940 h1:n5t5Jx3VpLdiAGxIvIHsZDmsExtZVwghUPLM3wFi6Go=
k8s.io/client-go v0.0.0-20260509205101-ca52b81a2940/go.mod h1:0e7OLwg7kdXISVFwn7ishFdvxfVgi7wsqHqsQPHl61w=
k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c=
k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y=
k8s.io/client-go v0.36.1 h1:FN/K8QIT2CEDt+2WB2HnWrUANZ50AP5GII43/SP2JR0=
k8s.io/client-go v0.36.1/go.mod h1:s6rAnCtTGYDQnpNjEhSaISV+2O8jwruZ6m3QOYBFbtU=
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
k8s.io/kube-openapi v0.0.0-20260511211612-da4e56fe5676 h1:ahjrVu/DBcaAhw/GcblfaOvvQ2wi8kqXWvn62nud3UU=
k8s.io/kube-openapi v0.0.0-20260511211612-da4e56fe5676/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY=
k8s.io/kube-openapi v0.0.0-20260520065146-aa012df4f4af h1:zLXA2Irn14q2/06WMkxViyr7YCPUO2lJ0QYE9Juy5vA=
k8s.io/kube-openapi v0.0.0-20260520065146-aa012df4f4af/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2 h1:AZYQSJemyQB5eRxqcPky+/7EdBj0xi3g0ZcxxJ7vbWU=
k8s.io/utils v0.0.0-20260210185600-b8788abfbbc2/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
+94
View File
@@ -0,0 +1,94 @@
package baseController
import (
"context"
"fmt"
"time"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
)
type SyncHandler func(ctx context.Context, objRef cache.ObjectName) error
type Controller struct {
workqueue workqueue.TypedRateLimitingInterface[cache.ObjectName]
recorder record.EventRecorder
synced cache.InformerSynced
syncHandler SyncHandler
}
func NewController(
ctx context.Context,
workqueue workqueue.TypedRateLimitingInterface[cache.ObjectName],
recorder record.EventRecorder,
synced cache.InformerSynced,
syncHandler SyncHandler,
) *Controller {
return &Controller{
workqueue: workqueue,
recorder: recorder,
synced: synced,
syncHandler: syncHandler,
}
}
func (c *Controller) Run(ctx context.Context, workers int) error {
defer utilruntime.HandleCrash()
defer c.workqueue.ShutDown()
logger := klog.FromContext(ctx)
logger.Info("Starting PolicyBinding controller")
logger.Info("Waiting for informer caches to sync")
if ok := cache.WaitForCacheSync(ctx.Done(), c.synced); !ok {
return fmt.Errorf("failed to wait for caches to sync")
}
logger.Info("Starting workers", "count", workers)
for i := 0; i < workers; i++ {
go wait.UntilWithContext(ctx, c.runWorker, time.Second)
}
logger.Info("Started workers")
<-ctx.Done()
logger.Info("Shutting down workers")
return nil
}
func (c *Controller) runWorker(ctx context.Context) {
for c.processNextWorkItem(ctx) {
}
}
func (c *Controller) processNextWorkItem(ctx context.Context) bool {
objRef, shutdown := c.workqueue.Get()
logger := klog.FromContext(ctx)
if shutdown {
return false
}
defer c.workqueue.Done(objRef)
err := c.syncHandler(ctx, objRef)
if err == nil {
c.workqueue.Forget(objRef)
logger.Info("Successfully synced", "objectName", objRef)
return true
}
utilruntime.HandleErrorWithContext(ctx, err, "Error syncing; requeuing for later retry", "objectReference", objRef)
c.workqueue.AddRateLimited(objRef)
return true
}
func (c *Controller) Enqueue(obj interface{}) {
objectRef, err := cache.ObjectToName(obj)
if err != nil {
utilruntime.HandleError(err)
return
}
c.workqueue.Add(objectRef)
}
+190
View File
@@ -0,0 +1,190 @@
// AI generated tests and not yet reviewed.
package baseController
import (
"context"
"errors"
"sync/atomic"
"testing"
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
)
func newTestController(t *testing.T, synced cache.InformerSynced, syncHandler SyncHandler) (*Controller, workqueue.TypedRateLimitingInterface[cache.ObjectName]) {
t.Helper()
ratelimiter := workqueue.NewTypedItemExponentialFailureRateLimiter[cache.ObjectName](time.Millisecond, time.Second)
q := workqueue.NewTypedRateLimitingQueue(ratelimiter)
t.Cleanup(q.ShutDown)
if synced == nil {
synced = func() bool { return true }
}
ctrl := NewController(
context.Background(),
q,
record.NewFakeRecorder(10),
synced,
syncHandler,
)
return ctrl, q
}
func TestController_processNextWorkItem_success(t *testing.T) {
objRef := cache.ObjectName{Namespace: "default", Name: "test"}
var syncedRef cache.ObjectName
ctrl, q := newTestController(t, nil, func(_ context.Context, ref cache.ObjectName) error {
syncedRef = ref
return nil
})
q.Add(objRef)
if !ctrl.processNextWorkItem(context.Background()) {
t.Fatal("processNextWorkItem() = false, want true")
}
if syncedRef != objRef {
t.Fatalf("syncHandler object = %+v, want %+v", syncedRef, objRef)
}
if q.Len() != 0 {
t.Fatalf("queue length = %d, want 0 after successful sync", q.Len())
}
if q.NumRequeues(objRef) != 0 {
t.Fatalf("requeues = %d, want 0 after successful sync", q.NumRequeues(objRef))
}
}
func TestController_processNextWorkItem_syncError(t *testing.T) {
objRef := cache.ObjectName{Namespace: "default", Name: "test"}
syncErr := errors.New("sync failed")
ctrl, q := newTestController(t, nil, func(context.Context, cache.ObjectName) error {
return syncErr
})
q.Add(objRef)
if !ctrl.processNextWorkItem(context.Background()) {
t.Fatal("processNextWorkItem() = false, want true")
}
if q.NumRequeues(objRef) != 1 {
t.Fatalf("requeues = %d, want 1 after sync error", q.NumRequeues(objRef))
}
}
func TestController_processNextWorkItem_shutdown(t *testing.T) {
ctrl, q := newTestController(t, nil, func(context.Context, cache.ObjectName) error {
return nil
})
q.ShutDown()
if ctrl.processNextWorkItem(context.Background()) {
t.Fatal("processNextWorkItem() = true, want false on shutdown")
}
}
func TestController_Enqueue(t *testing.T) {
ctrl, q := newTestController(t, nil, func(context.Context, cache.ObjectName) error {
return nil
})
obj := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: "default",
Name: "test",
},
}
ctrl.Enqueue(obj)
if q.Len() != 1 {
t.Fatalf("queue length = %d, want 1 after Enqueue", q.Len())
}
}
func TestController_Enqueue_invalidObject(t *testing.T) {
ctrl, q := newTestController(t, nil, func(context.Context, cache.ObjectName) error {
return nil
})
ctrl.Enqueue("not-a-kubernetes-object")
if q.Len() != 0 {
t.Fatalf("queue length = %d, want 0 for invalid object", q.Len())
}
}
func TestController_Run_cacheSyncFails(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
ctrl, _ := newTestController(t, func() bool { return false }, func(context.Context, cache.ObjectName) error {
return nil
})
go func() {
time.Sleep(10 * time.Millisecond)
cancel()
}()
err := ctrl.Run(ctx, 1)
if err == nil {
t.Fatal("Run() error = nil, want cache sync failure")
}
}
func TestController_Run_shutsDownOnCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
ctrl, _ := newTestController(t, nil, func(context.Context, cache.ObjectName) error {
return nil
})
errCh := make(chan error, 1)
go func() {
errCh <- ctrl.Run(ctx, 1)
}()
time.Sleep(50 * time.Millisecond)
cancel()
select {
case err := <-errCh:
if err != nil {
t.Fatalf("Run() error = %v, want nil on context cancel", err)
}
case <-time.After(2 * time.Second):
t.Fatal("Run() did not return after context cancellation")
}
}
func TestController_runWorker_processesQueuedItem(t *testing.T) {
objRef := cache.ObjectName{Namespace: "default", Name: "test"}
var calls atomic.Int32
ctrl, q := newTestController(t, nil, func(context.Context, cache.ObjectName) error {
calls.Add(1)
return nil
})
q.Add(objRef)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go ctrl.runWorker(ctx)
deadline := time.Now().Add(2 * time.Second)
for time.Now().Before(deadline) {
if calls.Load() == 1 && q.Len() == 0 {
cancel()
return
}
time.Sleep(5 * time.Millisecond)
}
cancel()
t.Fatalf("runWorker did not process queued item: calls=%d queueLen=%d", calls.Load(), q.Len())
}
+45 -5
View File
@@ -21,6 +21,7 @@ import (
"flag"
"net/url"
"os"
"sync"
"time"
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/signals"
@@ -32,6 +33,9 @@ import (
// Uncomment the following line to load the gcp plugin (only required to authenticate against GKE clusters).
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
applicationcontroller "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/controllers/application"
policybindingcontroller "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/controllers/policybinding"
proxyprovidercontroller "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/controllers/proxyprovider"
clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
informers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions"
)
@@ -61,7 +65,7 @@ func main() {
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
proxyProviderClient, err := clientset.NewForConfig(cfg)
clientset, err := clientset.NewForConfig(cfg)
if err != nil {
logger.Error(err, "Error building proxy provider clientset")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
@@ -73,20 +77,56 @@ func main() {
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
proxyProviderInformerFactory := informers.NewSharedInformerFactory(proxyProviderClient, time.Second*30)
proxyProviderInformerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
controller := NewController(ctx, kubeClient, proxyProviderClient, authentikClient,
ppController := proxyprovidercontroller.NewController(ctx, kubeClient, clientset, authentikClient,
proxyProviderInformerFactory.Proxyprovider().V1alpha1().ProxyProviders(),
)
applicationInformerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
appController := applicationcontroller.NewController(ctx, kubeClient, clientset, authentikClient,
applicationInformerFactory.Application().V1alpha1().Applications(),
)
policyBindingInformerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
pbController := policybindingcontroller.NewController(ctx, kubeClient, clientset, authentikClient,
policyBindingInformerFactory.PolicyBinding().V1alpha1().PolicyBindings(),
)
// notice that there is no need to run Start methods in a separate goroutine. (i.e. go kubeInformerFactory.Start(ctx.done())
// Start method is non-blocking and runs all registered informers in a dedicated goroutine.
proxyProviderInformerFactory.Start(ctx.Done())
applicationInformerFactory.Start(ctx.Done())
policyBindingInformerFactory.Start(ctx.Done())
if err = controller.Run(ctx, 2); err != nil {
logger.Error(err, "Error running controller")
var wg sync.WaitGroup
wg.Add(3)
go func() {
defer wg.Done()
if err := ppController.Run(ctx, 2); err != nil {
logger.Error(err, "Error running proxy provider controller")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
}()
go func() {
defer wg.Done()
if err := appController.Run(ctx, 2); err != nil {
logger.Error(err, "Error running application controller")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
}()
go func() {
defer wg.Done()
if err := pbController.Run(ctx, 2); err != nil {
logger.Error(err, "Error running policy binding controller")
klog.FlushAndExit(klog.ExitFlushTimeout, 1)
}
}()
wg.Wait()
}
func init() {
+23
View File
@@ -0,0 +1,23 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true
// +groupName=application.t000-n.de
// +groupGoName=Application
// Package v1alpha1 is the v1alpha1 version of the application API.
package v1alpha1
+52
View File
@@ -0,0 +1,52 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +kubebuilder:subresource:status
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type Application struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ApplicationSpec `json:"spec"`
Status ApplicationStatus `json:"status"`
}
type ApplicationSpec struct {
Name string `json:"name"`
Slug string `json:"slug"`
Provider int32 `json:"provider,omitempty"`
}
type ApplicationStatus struct {
PK string `json:"pk"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ApplicationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Application `json:"items"`
}
@@ -0,0 +1,119 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Application) DeepCopyInto(out *Application) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
out.Status = in.Status
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Application.
func (in *Application) DeepCopy() *Application {
if in == nil {
return nil
}
out := new(Application)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Application) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationList) DeepCopyInto(out *ApplicationList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Application, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationList.
func (in *ApplicationList) DeepCopy() *ApplicationList {
if in == nil {
return nil
}
out := new(ApplicationList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ApplicationList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec.
func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
if in == nil {
return nil
}
out := new(ApplicationSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationStatus) DeepCopyInto(out *ApplicationStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationStatus.
func (in *ApplicationStatus) DeepCopy() *ApplicationStatus {
if in == nil {
return nil
}
out := new(ApplicationStatus)
in.DeepCopyInto(out)
return out
}
@@ -0,0 +1,71 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by register-gen. DO NOT EDIT.
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName specifies the group name used to register the objects.
const GroupName = "application.t000-n.de"
// GroupVersion specifies the group and the version used to register the objects.
var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// SchemeGroupVersion is group version used to register these objects
//
// Deprecated: use GroupVersion instead.
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
// Deprecated: use Install instead
AddToScheme = localSchemeBuilder.AddToScheme
Install = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Application{},
&ApplicationList{},
)
// AddToGroupVersion allows the serialization of client types like ListOptions.
v1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
+23
View File
@@ -0,0 +1,23 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +k8s:deepcopy-gen=package
// +k8s:openapi-gen=true
// +groupName=policybinding.t000-n.de
// +groupGoName=PolicyBinding
// Package v1alpha1 is the v1alpha1 version of the policybinding API.
package v1alpha1
+54
View File
@@ -0,0 +1,54 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +kubebuilder:subresource:status
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type PolicyBinding struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec PolicyBindingSpec `json:"spec"`
Status PolicyBindingStatus `json:"status"`
}
type PolicyBindingSpec struct {
Policy string `json:"policy,omitempty"`
Group string `json:"group,omitempty"`
User int32 `json:"user,omitempty"`
Target string `json:"target"`
Order int32 `json:"order"`
}
type PolicyBindingStatus struct {
PK string `json:"pk"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type PolicyBindingList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []PolicyBinding `json:"items"`
}
@@ -0,0 +1,119 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1alpha1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyBinding) DeepCopyInto(out *PolicyBinding) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
out.Status = in.Status
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyBinding.
func (in *PolicyBinding) DeepCopy() *PolicyBinding {
if in == nil {
return nil
}
out := new(PolicyBinding)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PolicyBinding) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyBindingList) DeepCopyInto(out *PolicyBindingList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PolicyBinding, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyBindingList.
func (in *PolicyBindingList) DeepCopy() *PolicyBindingList {
if in == nil {
return nil
}
out := new(PolicyBindingList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PolicyBindingList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyBindingSpec) DeepCopyInto(out *PolicyBindingSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyBindingSpec.
func (in *PolicyBindingSpec) DeepCopy() *PolicyBindingSpec {
if in == nil {
return nil
}
out := new(PolicyBindingSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PolicyBindingStatus) DeepCopyInto(out *PolicyBindingStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyBindingStatus.
func (in *PolicyBindingStatus) DeepCopy() *PolicyBindingStatus {
if in == nil {
return nil
}
out := new(PolicyBindingStatus)
in.DeepCopyInto(out)
return out
}
@@ -0,0 +1,71 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by register-gen. DO NOT EDIT.
package v1alpha1
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName specifies the group name used to register the objects.
const GroupName = "policybinding.t000-n.de"
// GroupVersion specifies the group and the version used to register the objects.
var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// SchemeGroupVersion is group version used to register these objects
//
// Deprecated: use GroupVersion instead.
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
var (
// localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes.
SchemeBuilder runtime.SchemeBuilder
localSchemeBuilder = &SchemeBuilder
// Deprecated: use Install instead
AddToScheme = localSchemeBuilder.AddToScheme
Install = localSchemeBuilder.AddToScheme
)
func init() {
// We only register manually written functions here. The registration of the
// generated functions takes place in the generated files. The separation
// makes the code compile even when the generated files are missing.
localSchemeBuilder.Register(addKnownTypes)
}
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&PolicyBinding{},
&PolicyBindingList{},
)
// AddToGroupVersion allows the serialization of client types like ListOptions.
v1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
+1
View File
@@ -37,6 +37,7 @@ type ProxyProviderSpec struct {
AuthorizationFlow string `json:"authorization_flow"`
InvalidationFlow string `json:"invalidation_flow"`
ExternalHost string `json:"external_host"`
Outpost string `json:"outpost"`
}
type ProxyProviderStatus struct {
+230
View File
@@ -0,0 +1,230 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package application
import (
"context"
"fmt"
"net/http"
"slices"
"time"
"golang.org/x/time/rate"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/internal/baseController"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
operatorscheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
informers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/application/v1alpha1"
listers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/listers/application/v1alpha1"
authentikapi "goauthentik.io/api/v3"
)
const controllerAgentName = "application-controller"
const (
SuccessSynced = "Synced"
ErrResourceExists = "ErrResourceExists"
MessageResourceExists = "Resource %q already exists and is not managed by Application"
MessageResourceSynced = "Application synced successfully"
FieldManager = controllerAgentName
)
// Finalizers
const (
DeleteAuthentikApplicationFinalizer = "application.t000-n.de/delete-authentik-application"
)
type ApplicationController struct {
kubeclientset kubernetes.Interface
applicationClientset clientset.Interface
authentik *authentikapi.APIClient
applicationListener listers.ApplicationLister
controller *baseController.Controller
}
func NewController(
ctx context.Context,
kubeclientset kubernetes.Interface,
applicationClientset clientset.Interface,
authentik *authentikapi.APIClient,
applicationInformer informers.ApplicationInformer,
) *ApplicationController {
logger := klog.FromContext(ctx)
utilruntime.Must(operatorscheme.AddToScheme(scheme.Scheme))
logger.V(4).Info("Creating event broadcaster")
eventBroadcaster := record.NewBroadcaster(record.WithContext(ctx))
eventBroadcaster.StartStructuredLogging(0)
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events("")})
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerAgentName})
ratelimiter := workqueue.NewTypedMaxOfRateLimiter(
workqueue.NewTypedItemExponentialFailureRateLimiter[cache.ObjectName](5*time.Millisecond, 1000*time.Second),
&workqueue.TypedBucketRateLimiter[cache.ObjectName]{Limiter: rate.NewLimiter(rate.Limit(50), 300)},
)
c := &ApplicationController{
kubeclientset: kubeclientset,
applicationClientset: applicationClientset,
authentik: authentik,
applicationListener: applicationInformer.Lister(),
}
c.controller = baseController.NewController(
ctx,
workqueue.NewTypedRateLimitingQueue(ratelimiter),
recorder,
applicationInformer.Informer().HasSynced,
c.syncHandler,
)
logger.Info("Setting up event handlers")
applicationInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: c.controller.Enqueue,
UpdateFunc: func(_, newObj interface{}) {
c.controller.Enqueue(newObj)
},
})
return c
}
func (c *ApplicationController) Run(ctx context.Context, workers int) error {
return c.controller.Run(ctx, workers)
}
func (c *ApplicationController) syncHandler(ctx context.Context, objectRef cache.ObjectName) error {
logger := klog.LoggerWithValues(klog.FromContext(ctx), "objectRef", objectRef)
app, err := c.applicationListener.Applications(objectRef.Namespace).Get(objectRef.Name)
if err != nil {
if errors.IsNotFound(err) {
logger.V(4).Info("Application no longer exists")
return nil
}
return err
}
logger.V(4).Info("sync Application", "name", app.Name)
if !app.ObjectMeta.DeletionTimestamp.IsZero() {
logger.Info("Reconciling deletion of Application", "name", app.Name)
return c.reconcileDelete(ctx, app)
}
if app.Status.PK == "" {
logger.Info("Reconciling creation of Application", "name", app.Name)
return c.reconcileCreate(ctx, app)
}
// Check if all finalizers are present. If not, we add them. Same pattern as above, just needs a helper function to check for presence of a finalizer.
if !slices.Contains(app.ObjectMeta.Finalizers, DeleteAuthentikApplicationFinalizer) {
logger.Info("Ensuring finalizers are present", "name", app.Name)
return c.ensureFinalizers(ctx, app)
}
logger.Info("Reconciling update of Application", "name", app.Name)
return c.reconcileUpdate(ctx, app)
}
func (c *ApplicationController) ensureFinalizers(ctx context.Context, app *v1alpha1.Application) error {
app.ObjectMeta.Finalizers = append(app.ObjectMeta.Finalizers, DeleteAuthentikApplicationFinalizer)
return c.updateApplication(ctx, app)
}
func (c *ApplicationController) reconcileDelete(ctx context.Context, app *v1alpha1.Application) error {
r, err := c.authentik.CoreApi.CoreApplicationsDestroy(ctx, app.Spec.Slug).Execute()
if err != nil {
// This handles an edge-case, where when the Application on Authentik has already been deleted, but the finalizer is still present. We just remove the finalizer and return.
if r != nil && r.StatusCode != http.StatusNotFound {
return fmt.Errorf("error when calling `CoreAPI.CoreApplicationsDestroy`: %w with response %v", err, r)
}
}
app.ObjectMeta.Finalizers = slices.Delete(app.ObjectMeta.Finalizers, slices.Index(app.ObjectMeta.Finalizers, DeleteAuthentikApplicationFinalizer), 1)
return c.updateApplication(ctx, app)
}
func (c *ApplicationController) reconcileUpdate(ctx context.Context, app *v1alpha1.Application) error {
_, r, err := c.authentik.CoreApi.CoreApplicationsRetrieve(ctx, app.Spec.Slug).Execute()
if err != nil {
if r != nil && r.StatusCode == http.StatusNotFound {
// This handles an edge-case, where when the Application on Authentik has been deleted, e.g. by mistake. We just remove the PK and return.
// During the next reconciliation, the Application will be re-created.
app.Status.PK = ""
return c.updateApplicationStatus(ctx, app)
}
return fmt.Errorf("error retrieving existing Application: %v with response %v", err, r)
}
patchedApplicationRequest := &authentikapi.PatchedApplicationRequest{
Name: &app.Spec.Name,
Slug: &app.Spec.Slug,
Provider: *authentikapi.NewNullableInt32(&app.Spec.Provider),
}
resp, r, err := c.authentik.CoreApi.CoreApplicationsPartialUpdate(ctx, app.Spec.Slug).PatchedApplicationRequest(*patchedApplicationRequest).Execute()
if err != nil {
return fmt.Errorf("error when calling `CoreAPI.CoreApplicationsPartialUpdate`: %w with response %v", err, r)
}
app.Status.PK = resp.Pk
return c.updateApplicationStatus(ctx, app)
}
func (c *ApplicationController) reconcileCreate(ctx context.Context, app *v1alpha1.Application) error {
applicationRequest := &authentikapi.ApplicationRequest{
Name: app.Spec.Name,
Slug: app.Spec.Slug,
Provider: *authentikapi.NewNullableInt32(&app.Spec.Provider),
}
resp, r, err := c.authentik.CoreApi.CoreApplicationsCreate(ctx).ApplicationRequest(*applicationRequest).Execute()
if err != nil {
return fmt.Errorf("error when calling `CoreAPI.CoreApplicationsCreate`: %w with response %v", err, r)
}
app.Status.PK = resp.Pk
return c.updateApplicationStatus(ctx, app)
}
func (c *ApplicationController) updateApplicationStatus(ctx context.Context, app *v1alpha1.Application) error {
appCopy := app.DeepCopy()
_, err := c.applicationClientset.ApplicationV1alpha1().Applications(appCopy.Namespace).UpdateStatus(ctx, appCopy, metav1.UpdateOptions{FieldManager: FieldManager})
return err
}
// Update metadata, spec, etc. of the Application object.
func (c *ApplicationController) updateApplication(ctx context.Context, app *v1alpha1.Application) error {
appCopy := app.DeepCopy()
_, err := c.applicationClientset.ApplicationV1alpha1().Applications(appCopy.Namespace).Update(ctx, appCopy, metav1.UpdateOptions{FieldManager: FieldManager})
if err != nil {
return fmt.Errorf("error updating Application metadata: %v", err)
}
return nil
}
@@ -0,0 +1,377 @@
// AI generated tests and not yet reviewed.
package application
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/application/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{
applicationCreate: 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, testApplication(), server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: "default", Name: "test-app"})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getApplication(t, ctrl, "default", "test-app")
if got.Status.PK != wantPK {
t.Fatalf("status.pk = %q, want %q", got.Status.PK, wantPK)
}
}
func TestController_syncHandler_ensureFinalizers(t *testing.T) {
app := testApplication()
app.Status.PK = "42"
server := newAuthentikTestServer(t, authentikTestHandlers{})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, app, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: app.Namespace, Name: app.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getApplication(t, ctrl, app.Namespace, app.Name)
if !slices.Contains(got.Finalizers, DeleteAuthentikApplicationFinalizer) {
t.Fatalf("finalizers = %v, want %q", got.Finalizers, DeleteAuthentikApplicationFinalizer)
}
}
func TestController_syncHandler_update(t *testing.T) {
app := testApplication()
app.Status.PK = "42"
app.Finalizers = []string{DeleteAuthentikApplicationFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
applicationRetrieve: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{"pk": "42"})
},
applicationPartialUpdate: 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, app, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: app.Namespace, Name: app.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getApplication(t, ctrl, app.Namespace, app.Name)
if got.Status.PK != "42" {
t.Fatalf("status.pk = %q, want 42", got.Status.PK)
}
}
func TestController_syncHandler_update_applicationNotFound(t *testing.T) {
app := testApplication()
app.Status.PK = "42"
app.Finalizers = []string{DeleteAuthentikApplicationFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
applicationRetrieve: func(w http.ResponseWriter, _ *http.Request) {
http.NotFound(w, nil)
},
})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, app, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: app.Namespace, Name: app.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getApplication(t, ctrl, app.Namespace, app.Name)
if got.Status.PK != "" {
t.Fatalf("status.pk = %q, want empty after application not found", got.Status.PK)
}
}
func TestController_syncHandler_delete(t *testing.T) {
now := metav1.Now()
app := testApplication()
app.Status.PK = "42"
app.DeletionTimestamp = &now
app.Finalizers = []string{DeleteAuthentikApplicationFinalizer}
var destroyCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
applicationDestroy: 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, app, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: app.Namespace, Name: app.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
if !destroyCalled {
t.Fatal("expected Authentik destroy call")
}
got := getApplication(t, ctrl, app.Namespace, app.Name)
if slices.Contains(got.Finalizers, DeleteAuthentikApplicationFinalizer) {
t.Fatalf("finalizers = %v, want finalizer removed", got.Finalizers)
}
}
func TestController_syncHandler_delete_providerAlreadyGone(t *testing.T) {
now := metav1.Now()
app := testApplication()
app.Status.PK = "42"
app.DeletionTimestamp = &now
app.Finalizers = []string{DeleteAuthentikApplicationFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
applicationDestroy: func(w http.ResponseWriter, _ *http.Request) {
http.NotFound(w, nil)
},
})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, app, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: app.Namespace, Name: app.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getApplication(t, ctrl, app.Namespace, app.Name)
if slices.Contains(got.Finalizers, DeleteAuthentikApplicationFinalizer) {
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_delete_usesSlugNotPK(t *testing.T) {
now := metav1.Now()
app := testApplication()
app.Status.PK = "not-a-number"
app.DeletionTimestamp = &now
app.Finalizers = []string{DeleteAuthentikApplicationFinalizer}
var destroySlug string
server := newAuthentikTestServer(t, authentikTestHandlers{
applicationDestroy: func(w http.ResponseWriter, r *http.Request) {
destroySlug = strings.TrimSuffix(strings.TrimPrefix(r.URL.Path, "/api/v3/core/applications/"), "/")
w.WriteHeader(http.StatusNoContent)
},
})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, app, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: app.Namespace, Name: app.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
if destroySlug != app.Spec.Slug {
t.Fatalf("destroy slug = %q, want %q (delete must use spec.slug, not status.pk)", destroySlug, app.Spec.Slug)
}
}
// --- test helpers ---
func testApplication() *v1alpha1.Application {
return &v1alpha1.Application{
TypeMeta: metav1.TypeMeta{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: "Application",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-app",
Namespace: "default",
},
Spec: v1alpha1.ApplicationSpec{
Name: "My Application",
Slug: "my-app",
Provider: 7,
},
}
}
func newTestController(t *testing.T, app *v1alpha1.Application, authentikURL string) (*ApplicationController, context.Context, context.CancelFunc) {
t.Helper()
ctx, cancel := context.WithCancel(context.Background())
ctrl, _, stop := newTestControllerWithContext(t, ctx, app, authentikURL)
return ctrl, ctx, func() {
cancel()
stop()
}
}
func newTestControllerWithContext(t *testing.T, ctx context.Context, app *v1alpha1.Application, authentikURL string) (*ApplicationController, context.Context, func()) {
t.Helper()
authentikClient := newAuthentikAPIClientForTest(t, authentikURL)
var objects []runtime.Object
if app != nil {
objects = append(objects, app)
}
applicationClient := operatorfake.NewSimpleClientset(objects...)
informerFactory := operatorinformers.NewSharedInformerFactory(applicationClient, 0)
applicationInformer := informerFactory.Application().V1alpha1().Applications()
ctrl := NewController(ctx, fake.NewClientset(), applicationClient, authentikClient, applicationInformer)
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 {
applicationCreate http.HandlerFunc
applicationRetrieve http.HandlerFunc
applicationPartialUpdate http.HandlerFunc
applicationDestroy 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/core/applications/" && r.Method == http.MethodPost:
if handlers.applicationCreate != nil {
handlers.applicationCreate(w, r)
return
}
http.NotFound(w, r)
case strings.HasPrefix(path, "/api/v3/core/applications/") && strings.HasSuffix(path, "/"):
slugPath := strings.TrimPrefix(path, "/api/v3/core/applications/")
if slugPath == "" {
http.NotFound(w, r)
return
}
switch r.Method {
case http.MethodGet:
if handlers.applicationRetrieve != nil {
handlers.applicationRetrieve(w, r)
return
}
http.NotFound(w, r)
case http.MethodPatch:
if handlers.applicationPartialUpdate != nil {
handlers.applicationPartialUpdate(w, r)
return
}
http.NotFound(w, r)
case http.MethodDelete:
if handlers.applicationDestroy != nil {
handlers.applicationDestroy(w, r)
return
}
http.NotFound(w, r)
default:
http.Error(w, "unexpected method on application instance", http.StatusMethodNotAllowed)
}
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 getApplication(t *testing.T, ctrl *ApplicationController, namespace, name string) *v1alpha1.Application {
t.Helper()
got, err := ctrl.applicationClientset.ApplicationV1alpha1().Applications(namespace).Get(
context.Background(), name, metav1.GetOptions{},
)
if err != nil {
t.Fatalf("get Application: %v", err)
}
return got
}
+245
View File
@@ -0,0 +1,245 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package policybinding
import (
"context"
"fmt"
"net/http"
"slices"
"time"
"golang.org/x/time/rate"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/internal/baseController"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
operatorscheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
informers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/policybinding/v1alpha1"
listers "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/listers/policybinding/v1alpha1"
authentikapi "goauthentik.io/api/v3"
)
const controllerAgentName = "policybinding-controller"
const (
SuccessSynced = "Synced"
ErrResourceExists = "ErrResourceExists"
MessageResourceExists = "Resource %q already exists and is not managed by PolicyBinding"
MessageResourceSynced = "PolicyBinding synced successfully"
FieldManager = controllerAgentName
)
// Finalizers
const (
DeleteAuthentikPolicyBindingFinalizer = "policybinding.t000-n.de/delete-authentik-policybinding"
)
type PolicyBindingController struct {
kubeclientset kubernetes.Interface
policyBindingClientset clientset.Interface
authentik *authentikapi.APIClient
policyBindingListener listers.PolicyBindingLister
controller *baseController.Controller
}
func NewController(
ctx context.Context,
kubeclientset kubernetes.Interface,
policyBindingClientset clientset.Interface,
authentik *authentikapi.APIClient,
policyBindingInformer informers.PolicyBindingInformer,
) *PolicyBindingController {
logger := klog.FromContext(ctx)
utilruntime.Must(operatorscheme.AddToScheme(scheme.Scheme))
logger.V(4).Info("Creating event broadcaster")
eventBroadcaster := record.NewBroadcaster(record.WithContext(ctx))
eventBroadcaster.StartStructuredLogging(0)
eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events("")})
recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerAgentName})
ratelimiter := workqueue.NewTypedMaxOfRateLimiter(
workqueue.NewTypedItemExponentialFailureRateLimiter[cache.ObjectName](5*time.Millisecond, 1000*time.Second),
&workqueue.TypedBucketRateLimiter[cache.ObjectName]{Limiter: rate.NewLimiter(rate.Limit(50), 300)},
)
c := &PolicyBindingController{
kubeclientset: kubeclientset,
policyBindingClientset: policyBindingClientset,
authentik: authentik,
policyBindingListener: policyBindingInformer.Lister(),
}
c.controller = baseController.NewController(
ctx,
workqueue.NewTypedRateLimitingQueue(ratelimiter),
recorder,
policyBindingInformer.Informer().HasSynced,
c.syncHandler,
)
logger.Info("Setting up event handlers")
policyBindingInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: c.controller.Enqueue,
UpdateFunc: func(_, newObj interface{}) {
c.controller.Enqueue(newObj)
},
})
return c
}
func (c *PolicyBindingController) Run(ctx context.Context, workers int) error {
return c.controller.Run(ctx, workers)
}
func (c *PolicyBindingController) syncHandler(ctx context.Context, objectRef cache.ObjectName) error {
logger := klog.LoggerWithValues(klog.FromContext(ctx), "objectRef", objectRef)
pb, err := c.policyBindingListener.PolicyBindings(objectRef.Namespace).Get(objectRef.Name)
if err != nil {
if errors.IsNotFound(err) {
logger.V(4).Info("PolicyBinding no longer exists")
return nil
}
return err
}
logger.V(4).Info("sync PolicyBinding", "name", pb.Name)
if !pb.ObjectMeta.DeletionTimestamp.IsZero() {
logger.Info("Reconciling deletion of PolicyBinding", "name", pb.Name)
return c.reconcileDelete(ctx, pb)
}
if pb.Status.PK == "" {
logger.Info("Reconciling creation of PolicyBinding", "name", pb.Name)
return c.reconcileCreate(ctx, pb)
}
// Check if all finalizers are present. If not, we add them. Same pattern as above, just needs a helper function to check for presence of a finalizer.
if !slices.Contains(pb.ObjectMeta.Finalizers, DeleteAuthentikPolicyBindingFinalizer) {
logger.Info("Ensuring finalizers are present", "name", pb.Name)
return c.ensureFinalizers(ctx, pb)
}
logger.Info("Reconciling update of PolicyBinding", "name", pb.Name)
return c.reconcileUpdate(ctx, pb)
}
func (c *PolicyBindingController) ensureFinalizers(ctx context.Context, pb *v1alpha1.PolicyBinding) error {
pb.ObjectMeta.Finalizers = append(pb.ObjectMeta.Finalizers, DeleteAuthentikPolicyBindingFinalizer)
return c.updatePolicyBinding(ctx, pb)
}
func (c *PolicyBindingController) reconcileDelete(ctx context.Context, pb *v1alpha1.PolicyBinding) error {
r, err := c.authentik.PoliciesApi.PoliciesBindingsDestroy(ctx, pb.Status.PK).Execute()
if err != nil {
// This handles an edge-case, where when the PolicyBinding on Authentik has already been deleted, but the finalizer is still present. We just remove the finalizer and return.
if r != nil && r.StatusCode != http.StatusNotFound {
return fmt.Errorf("error when calling `PoliciesAPI.PoliciesBindingsDestroy`: %w with response %v", err, r)
}
}
pb.ObjectMeta.Finalizers = slices.Delete(pb.ObjectMeta.Finalizers, slices.Index(pb.ObjectMeta.Finalizers, DeleteAuthentikPolicyBindingFinalizer), 1)
return c.updatePolicyBinding(ctx, pb)
}
func (c *PolicyBindingController) reconcileUpdate(ctx context.Context, pb *v1alpha1.PolicyBinding) error {
_, r, err := c.authentik.PoliciesApi.PoliciesBindingsRetrieve(ctx, pb.Status.PK).Execute()
if err != nil {
if r != nil && r.StatusCode == http.StatusNotFound {
// This handles an edge-case, where when the PolicyBinding on Authentik has been deleted, e.g. by mistake. We just remove the PK and return.
// During the next reconciliation, the PolicyBinding will be re-created.
pb.Status.PK = ""
return c.updatePolicyBindingStatus(ctx, pb)
}
return fmt.Errorf("error retrieving existing PolicyBinding: %v with response %v", err, r)
}
patchedPolicyBindingRequest := &authentikapi.PatchedPolicyBindingRequest{
Target: &pb.Spec.Target,
Order: &pb.Spec.Order,
}
if pb.Spec.Policy != "" {
patchedPolicyBindingRequest.SetPolicy(pb.Spec.Policy)
}
if pb.Spec.Group != "" {
patchedPolicyBindingRequest.SetGroup(pb.Spec.Group)
}
if pb.Spec.User != 0 {
patchedPolicyBindingRequest.SetUser(pb.Spec.User)
}
resp, r, err := c.authentik.PoliciesApi.PoliciesBindingsPartialUpdate(ctx, pb.Status.PK).PatchedPolicyBindingRequest(*patchedPolicyBindingRequest).Execute()
if err != nil {
return fmt.Errorf("error when calling `PoliciesAPI.PoliciesBindingsPartialUpdate`: %w with response %v", err, r)
}
pb.Status.PK = resp.Pk
return c.updatePolicyBindingStatus(ctx, pb)
}
func (c *PolicyBindingController) reconcileCreate(ctx context.Context, pb *v1alpha1.PolicyBinding) error {
policyBindingRequest := &authentikapi.PolicyBindingRequest{
Target: pb.Spec.Target,
Order: pb.Spec.Order,
}
if pb.Spec.Policy != "" {
policyBindingRequest.SetPolicy(pb.Spec.Policy)
}
if pb.Spec.Group != "" {
policyBindingRequest.SetGroup(pb.Spec.Group)
}
if pb.Spec.User != 0 {
policyBindingRequest.SetUser(pb.Spec.User)
}
resp, r, err := c.authentik.PoliciesApi.PoliciesBindingsCreate(ctx).PolicyBindingRequest(*policyBindingRequest).Execute()
if err != nil {
return fmt.Errorf("error when calling `PoliciesAPI.PoliciesBindingsCreate`: %w with response %v", err, r)
}
pb.Status.PK = resp.Pk
return c.updatePolicyBindingStatus(ctx, pb)
}
func (c *PolicyBindingController) updatePolicyBindingStatus(ctx context.Context, pb *v1alpha1.PolicyBinding) error {
pbCopy := pb.DeepCopy()
_, err := c.policyBindingClientset.PolicyBindingV1alpha1().PolicyBindings(pbCopy.Namespace).UpdateStatus(ctx, pbCopy, metav1.UpdateOptions{FieldManager: FieldManager})
return err
}
// Update metadata, spec, etc. of the PolicyBinding object.
func (c *PolicyBindingController) updatePolicyBinding(ctx context.Context, pb *v1alpha1.PolicyBinding) error {
pbCopy := pb.DeepCopy()
_, err := c.policyBindingClientset.PolicyBindingV1alpha1().PolicyBindings(pbCopy.Namespace).Update(ctx, pbCopy, metav1.UpdateOptions{FieldManager: FieldManager})
return err
}
@@ -0,0 +1,349 @@
// AI generated tests and not yet reviewed.
package policybinding
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/policybinding/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{
policyBindingCreate: 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, testPolicyBinding(), server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: "default", Name: "test-pb"})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getPolicyBinding(t, ctrl, "default", "test-pb")
if got.Status.PK != wantPK {
t.Fatalf("status.pk = %q, want %q", got.Status.PK, wantPK)
}
}
func TestController_syncHandler_ensureFinalizers(t *testing.T) {
pb := testPolicyBinding()
pb.Status.PK = "42"
server := newAuthentikTestServer(t, authentikTestHandlers{})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, pb, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pb.Namespace, Name: pb.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getPolicyBinding(t, ctrl, pb.Namespace, pb.Name)
if !slices.Contains(got.Finalizers, DeleteAuthentikPolicyBindingFinalizer) {
t.Fatalf("finalizers = %v, want %q", got.Finalizers, DeleteAuthentikPolicyBindingFinalizer)
}
}
func TestController_syncHandler_update(t *testing.T) {
pb := testPolicyBinding()
pb.Status.PK = "42"
pb.Finalizers = []string{DeleteAuthentikPolicyBindingFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
policyBindingRetrieve: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{"pk": "42"})
},
policyBindingPartialUpdate: 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, pb, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pb.Namespace, Name: pb.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getPolicyBinding(t, ctrl, pb.Namespace, pb.Name)
if got.Status.PK != "42" {
t.Fatalf("status.pk = %q, want 42", got.Status.PK)
}
}
func TestController_syncHandler_update_policyBindingNotFound(t *testing.T) {
pb := testPolicyBinding()
pb.Status.PK = "42"
pb.Finalizers = []string{DeleteAuthentikPolicyBindingFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
policyBindingRetrieve: func(w http.ResponseWriter, _ *http.Request) {
http.NotFound(w, nil)
},
})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, pb, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pb.Namespace, Name: pb.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getPolicyBinding(t, ctrl, pb.Namespace, pb.Name)
if got.Status.PK != "" {
t.Fatalf("status.pk = %q, want empty after policy binding not found", got.Status.PK)
}
}
func TestController_syncHandler_delete(t *testing.T) {
now := metav1.Now()
pb := testPolicyBinding()
pb.Status.PK = "42"
pb.DeletionTimestamp = &now
pb.Finalizers = []string{DeleteAuthentikPolicyBindingFinalizer}
var destroyCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
policyBindingDestroy: 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, pb, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pb.Namespace, Name: pb.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
if !destroyCalled {
t.Fatal("expected Authentik destroy call")
}
got := getPolicyBinding(t, ctrl, pb.Namespace, pb.Name)
if slices.Contains(got.Finalizers, DeleteAuthentikPolicyBindingFinalizer) {
t.Fatalf("finalizers = %v, want finalizer removed", got.Finalizers)
}
}
func TestController_syncHandler_delete_policyBindingAlreadyGone(t *testing.T) {
now := metav1.Now()
pb := testPolicyBinding()
pb.Status.PK = "42"
pb.DeletionTimestamp = &now
pb.Finalizers = []string{DeleteAuthentikPolicyBindingFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
policyBindingDestroy: func(w http.ResponseWriter, _ *http.Request) {
http.NotFound(w, nil)
},
})
t.Cleanup(server.Close)
ctrl, ctx, cancel := newTestController(t, pb, server.URL)
t.Cleanup(cancel)
err := ctrl.syncHandler(ctx, cache.ObjectName{Namespace: pb.Namespace, Name: pb.Name})
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
got := getPolicyBinding(t, ctrl, pb.Namespace, pb.Name)
if slices.Contains(got.Finalizers, DeleteAuthentikPolicyBindingFinalizer) {
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)
}
}
// --- test helpers ---
func testPolicyBinding() *v1alpha1.PolicyBinding {
return &v1alpha1.PolicyBinding{
TypeMeta: metav1.TypeMeta{
APIVersion: v1alpha1.SchemeGroupVersion.String(),
Kind: "PolicyBinding",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-pb",
Namespace: "default",
},
Spec: v1alpha1.PolicyBindingSpec{
Group: "14ab813f-a7f9-481b-9b08-781953ae9ebf",
Target: "8dd85627-9c48-49c2-8afc-d73dd122ffc2",
Order: 1,
},
}
}
func newTestController(t *testing.T, pb *v1alpha1.PolicyBinding, authentikURL string) (*PolicyBindingController, context.Context, context.CancelFunc) {
t.Helper()
ctx, cancel := context.WithCancel(context.Background())
ctrl, _, stop := newTestControllerWithContext(t, ctx, pb, authentikURL)
return ctrl, ctx, func() {
cancel()
stop()
}
}
func newTestControllerWithContext(t *testing.T, ctx context.Context, pb *v1alpha1.PolicyBinding, authentikURL string) (*PolicyBindingController, context.Context, func()) {
t.Helper()
authentikClient := newAuthentikAPIClientForTest(t, authentikURL)
var objects []runtime.Object
if pb != nil {
objects = append(objects, pb)
}
policyBindingClient := operatorfake.NewSimpleClientset(objects...)
informerFactory := operatorinformers.NewSharedInformerFactory(policyBindingClient, 0)
policyBindingInformer := informerFactory.PolicyBinding().V1alpha1().PolicyBindings()
ctrl := NewController(ctx, fake.NewClientset(), policyBindingClient, authentikClient, policyBindingInformer)
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 {
policyBindingCreate http.HandlerFunc
policyBindingRetrieve http.HandlerFunc
policyBindingPartialUpdate http.HandlerFunc
policyBindingDestroy 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/policies/bindings/" && r.Method == http.MethodPost:
if handlers.policyBindingCreate != nil {
handlers.policyBindingCreate(w, r)
return
}
http.NotFound(w, r)
case strings.HasPrefix(path, "/api/v3/policies/bindings/") && strings.HasSuffix(path, "/"):
idPath := strings.TrimPrefix(path, "/api/v3/policies/bindings/")
if idPath == "" {
http.NotFound(w, r)
return
}
switch r.Method {
case http.MethodGet:
if handlers.policyBindingRetrieve != nil {
handlers.policyBindingRetrieve(w, r)
return
}
http.NotFound(w, r)
case http.MethodPatch:
if handlers.policyBindingPartialUpdate != nil {
handlers.policyBindingPartialUpdate(w, r)
return
}
http.NotFound(w, r)
case http.MethodDelete:
if handlers.policyBindingDestroy != nil {
handlers.policyBindingDestroy(w, r)
return
}
http.NotFound(w, r)
default:
http.Error(w, "unexpected method on policy binding instance", http.StatusMethodNotAllowed)
}
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 getPolicyBinding(t *testing.T, ctrl *PolicyBindingController, namespace, name string) *v1alpha1.PolicyBinding {
t.Helper()
got, err := ctrl.policyBindingClientset.PolicyBindingV1alpha1().PolicyBindings(namespace).Get(
context.Background(), name, metav1.GetOptions{},
)
if err != nil {
t.Fatalf("get PolicyBinding: %v", err)
}
return got
}
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package proxyprovider
import (
"context"
@@ -30,7 +30,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
@@ -39,6 +38,7 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/klog/v2"
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/internal/baseController"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
operatorscheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
@@ -62,16 +62,14 @@ const (
DeleteAuthentikProxyProviderFinalizer = "proxyprovider.t000-n.de/delete-authentik-proxyprovider"
)
type Controller struct {
type ProxyProviderController struct {
kubeclientset kubernetes.Interface
proxyProviderClientset clientset.Interface
authentik *authentikapi.APIClient
proxyLister listers.ProxyProviderLister
proxySynced cache.InformerSynced
workqueue workqueue.TypedRateLimitingInterface[cache.ObjectName]
recorder record.EventRecorder
controller *baseController.Controller
}
func NewController(
@@ -80,7 +78,7 @@ func NewController(
proxyProviderClientset clientset.Interface,
authentik *authentikapi.APIClient,
proxyInformer informers.ProxyProviderInformer,
) *Controller {
) *ProxyProviderController {
logger := klog.FromContext(ctx)
utilruntime.Must(operatorscheme.AddToScheme(scheme.Scheme))
@@ -95,75 +93,36 @@ func NewController(
&workqueue.TypedBucketRateLimiter[cache.ObjectName]{Limiter: rate.NewLimiter(rate.Limit(50), 300)},
)
c := &Controller{
c := &ProxyProviderController{
kubeclientset: kubeclientset,
proxyProviderClientset: proxyProviderClientset,
authentik: authentik,
proxyLister: proxyInformer.Lister(),
proxySynced: proxyInformer.Informer().HasSynced,
workqueue: workqueue.NewTypedRateLimitingQueue(ratelimiter),
recorder: recorder,
}
c.controller = baseController.NewController(
ctx,
workqueue.NewTypedRateLimitingQueue(ratelimiter),
recorder,
proxyInformer.Informer().HasSynced,
c.syncHandler,
)
logger.Info("Setting up event handlers")
proxyInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: c.enqueueProxyProvider,
AddFunc: c.controller.Enqueue,
UpdateFunc: func(_, newObj interface{}) {
c.enqueueProxyProvider(newObj)
c.controller.Enqueue(newObj)
},
})
return c
}
func (c *Controller) Run(ctx context.Context, workers int) error {
defer utilruntime.HandleCrash()
defer c.workqueue.ShutDown()
logger := klog.FromContext(ctx)
logger.Info("Starting ProxyProvider controller")
logger.Info("Waiting for informer caches to sync")
if ok := cache.WaitForCacheSync(ctx.Done(), c.proxySynced); !ok {
return fmt.Errorf("failed to wait for caches to sync")
}
logger.Info("Starting workers", "count", workers)
for i := 0; i < workers; i++ {
go wait.UntilWithContext(ctx, c.runWorker, time.Second)
}
logger.Info("Started workers")
<-ctx.Done()
logger.Info("Shutting down workers")
return nil
func (c *ProxyProviderController) Run(ctx context.Context, workers int) error {
return c.controller.Run(ctx, workers)
}
func (c *Controller) runWorker(ctx context.Context) {
for c.processNextWorkItem(ctx) {
}
}
func (c *Controller) processNextWorkItem(ctx context.Context) bool {
objRef, shutdown := c.workqueue.Get()
logger := klog.FromContext(ctx)
if shutdown {
return false
}
defer c.workqueue.Done(objRef)
err := c.syncHandler(ctx, objRef)
if err == nil {
c.workqueue.Forget(objRef)
logger.Info("Successfully synced", "objectName", objRef)
return true
}
utilruntime.HandleErrorWithContext(ctx, err, "Error syncing; requeuing for later retry", "objectReference", objRef)
c.workqueue.AddRateLimited(objRef)
return true
}
func (c *Controller) syncHandler(ctx context.Context, objectRef cache.ObjectName) error {
func (c *ProxyProviderController) syncHandler(ctx context.Context, objectRef cache.ObjectName) error {
logger := klog.LoggerWithValues(klog.FromContext(ctx), "objectRef", objectRef)
pp, err := c.proxyLister.ProxyProviders(objectRef.Namespace).Get(objectRef.Name)
@@ -196,17 +155,23 @@ func (c *Controller) syncHandler(ctx context.Context, objectRef cache.ObjectName
return c.reconcileUpdate(ctx, pp)
}
func (c *Controller) ensureFinalizers(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
func (c *ProxyProviderController) ensureFinalizers(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
pp.ObjectMeta.Finalizers = append(pp.ObjectMeta.Finalizers, DeleteAuthentikProxyProviderFinalizer)
return c.updateProxyProvider(ctx, pp)
}
func (c *Controller) reconcileDelete(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
func (c *ProxyProviderController) reconcileDelete(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
pk, err := strconv.ParseInt(pp.Status.PK, 10, 32)
if err != nil {
return fmt.Errorf("error parsing PK: %v", err)
}
err = c.reconcileOutpost(ctx, pp.Spec.Outpost, int32(pk), ReconcileOutpostModeRemove)
if err != nil {
return fmt.Errorf("error when calling `reconcileOutpost`: %w", err)
}
// Delete ProxyProvider
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.
@@ -219,7 +184,7 @@ func (c *Controller) reconcileDelete(ctx context.Context, pp *v1alpha1.ProxyProv
return c.updateProxyProvider(ctx, pp)
}
func (c *Controller) reconcileUpdate(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
func (c *ProxyProviderController) reconcileUpdate(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
// We retrieve the existing PP from the API by slug.
pk, err := strconv.ParseInt(pp.Status.PK, 10, 32)
if err != nil {
@@ -247,13 +212,17 @@ func (c *Controller) reconcileUpdate(ctx context.Context, pp *v1alpha1.ProxyProv
if err != nil {
return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyPartialUpdate`: %w with response %v", err, r)
}
pp.Status.PK = strconv.Itoa(int(resp.Pk))
err = c.reconcileOutpost(ctx, pp.Spec.Outpost, int32(pk), ReconcileOutpostModeAdd)
if err != nil {
return fmt.Errorf("error when calling `reconcileOutpost`: %w", err)
}
return c.updateProxyProviderStatus(ctx, pp)
}
func (c *Controller) reconcileCreate(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
func (c *ProxyProviderController) reconcileCreate(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
proxyProviderRequest := &authentikapi.ProxyProviderRequest{
Name: pp.Spec.Name,
AuthorizationFlow: pp.Spec.AuthorizationFlow,
@@ -266,27 +235,23 @@ func (c *Controller) reconcileCreate(ctx context.Context, pp *v1alpha1.ProxyProv
return fmt.Errorf("error when calling `ProvidersAPI.ProvidersProxyCreate`: %w with response %v", err, r)
}
err = c.reconcileOutpost(ctx, pp.Spec.Outpost, resp.Pk, ReconcileOutpostModeAdd)
if err != nil {
return fmt.Errorf("error when calling `reconcileOutpost`: %w", err)
}
pp.Status.PK = strconv.Itoa(int(resp.Pk))
return c.updateProxyProviderStatus(ctx, pp)
}
func (c *Controller) enqueueProxyProvider(obj interface{}) {
objectRef, err := cache.ObjectToName(obj)
if err != nil {
utilruntime.HandleError(err)
return
}
c.workqueue.Add(objectRef)
}
func (c *Controller) updateProxyProviderStatus(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
func (c *ProxyProviderController) updateProxyProviderStatus(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
ppCopy := pp.DeepCopy()
_, err := c.proxyProviderClientset.ProxyproviderV1alpha1().ProxyProviders(ppCopy.Namespace).UpdateStatus(ctx, ppCopy, metav1.UpdateOptions{FieldManager: FieldManager})
return err
}
// Update metadata, spec, etc. of the ProxyProvider object.
func (c *Controller) updateProxyProvider(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
func (c *ProxyProviderController) updateProxyProvider(ctx context.Context, pp *v1alpha1.ProxyProvider) error {
ppCopy := pp.DeepCopy()
_, err := c.proxyProviderClientset.ProxyproviderV1alpha1().ProxyProviders(ppCopy.Namespace).Update(ctx, ppCopy, metav1.UpdateOptions{FieldManager: FieldManager})
if err != nil {
@@ -294,3 +259,51 @@ func (c *Controller) updateProxyProvider(ctx context.Context, pp *v1alpha1.Proxy
}
return nil
}
type ReconcileOutpostMode string
const (
ReconcileOutpostModeAdd ReconcileOutpostMode = "add"
ReconcileOutpostModeRemove ReconcileOutpostMode = "remove"
)
func (c *ProxyProviderController) reconcileOutpost(ctx context.Context, outpostId string, providerPk int32, mode ReconcileOutpostMode) error {
logger := klog.LoggerWithValues(klog.FromContext(ctx), "outpostId", outpostId, "providerPk", providerPk, "mode", mode)
outpost, r, err := c.authentik.OutpostsApi.OutpostsInstancesRetrieve(ctx, outpostId).Execute()
if err != nil {
return fmt.Errorf("error when calling `OutpostsAPI.OutpostsInstancesRetrieve`: %w with response %v", err, r)
}
updated := false
switch mode {
case ReconcileOutpostModeAdd:
if !slices.Contains(outpost.Providers, providerPk) {
outpost.Providers = append(outpost.Providers, providerPk)
updated = true
} else {
logger.V(4).Info("Provider already in outpost")
}
case ReconcileOutpostModeRemove:
if slices.Contains(outpost.Providers, providerPk) {
outpost.Providers = slices.Delete(outpost.Providers, slices.Index(outpost.Providers, providerPk), 1)
updated = true
}
default:
return fmt.Errorf("invalid mode: %s", mode)
}
if !updated {
return nil
}
outpostPartialUpdateRequest := &authentikapi.PatchedOutpostRequest{
Providers: outpost.Providers,
}
_, r, err = c.authentik.OutpostsApi.OutpostsInstancesPartialUpdate(ctx, outpostId).PatchedOutpostRequest(*outpostPartialUpdateRequest).Execute()
if err != nil {
return fmt.Errorf("error when calling `OutpostsAPI.OutpostsInstancesPartialUpdate`: %w with response %v", err, r)
}
return nil
}
@@ -1,5 +1,5 @@
// AI generated tests and not yet reviewed.
package main
package proxyprovider
import (
"context"
@@ -21,13 +21,30 @@ import (
"k8s.io/client-go/tools/cache"
)
const testOutpostID = "550e8400-e29b-41d4-a716-446655440000"
func TestController_syncHandler_create(t *testing.T) {
const wantPK = 42
var outpostPartialUpdateCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
proxyCreate: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusCreated, map[string]any{"pk": wantPK})
},
outpostRetrieve: outpostRetrieveHandler(t, nil),
outpostPartialUpdate: func(w http.ResponseWriter, r *http.Request) {
outpostPartialUpdateCalled = true
var body struct {
Providers []int32 `json:"providers"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatalf("decode outpost patch body: %v", err)
}
if !slices.Contains(body.Providers, wantPK) {
t.Fatalf("patched providers = %v, want to contain %d", body.Providers, wantPK)
}
writeJSON(t, w, http.StatusOK, map[string]any{"pk": testOutpostID, "providers": body.Providers})
},
})
t.Cleanup(server.Close)
@@ -38,6 +55,41 @@ func TestController_syncHandler_create(t *testing.T) {
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
if !outpostPartialUpdateCalled {
t.Fatal("expected Authentik outpost partial update call")
}
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_create_providerAlreadyInOutpost(t *testing.T) {
const wantPK = 42
var outpostPartialUpdateCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
proxyCreate: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusCreated, map[string]any{"pk": wantPK})
},
outpostRetrieve: outpostRetrieveHandler(t, []int32{wantPK}),
outpostPartialUpdate: func(w http.ResponseWriter, _ *http.Request) {
outpostPartialUpdateCalled = true
},
})
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)
}
if outpostPartialUpdateCalled {
t.Fatal("did not expect Authentik outpost partial update when provider is already present")
}
got := getProxyProvider(t, ctrl, "default", "test-pp")
if got.Status.PK != "42" {
@@ -71,6 +123,7 @@ func TestController_syncHandler_update(t *testing.T) {
pp.Status.PK = "42"
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
var outpostPartialUpdateCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
allRetrieve: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42})
@@ -78,6 +131,20 @@ func TestController_syncHandler_update(t *testing.T) {
proxyPartialUpdate: func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{"pk": 42})
},
outpostRetrieve: outpostRetrieveHandler(t, nil),
outpostPartialUpdate: func(w http.ResponseWriter, r *http.Request) {
outpostPartialUpdateCalled = true
var body struct {
Providers []int32 `json:"providers"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatalf("decode outpost patch body: %v", err)
}
if !slices.Contains(body.Providers, 42) {
t.Fatalf("patched providers = %v, want to contain 42", body.Providers)
}
writeJSON(t, w, http.StatusOK, map[string]any{"pk": testOutpostID, "providers": body.Providers})
},
})
t.Cleanup(server.Close)
@@ -88,6 +155,9 @@ func TestController_syncHandler_update(t *testing.T) {
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
if !outpostPartialUpdateCalled {
t.Fatal("expected Authentik outpost partial update call")
}
got := getProxyProvider(t, ctrl, pp.Namespace, pp.Name)
if got.Status.PK != "42" {
@@ -122,14 +192,29 @@ func TestController_syncHandler_update_providerNotFound(t *testing.T) {
}
func TestController_syncHandler_delete(t *testing.T) {
const wantPK int32 = 42
now := metav1.Now()
pp := testProxyProvider()
pp.Status.PK = "42"
pp.DeletionTimestamp = &now
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
var destroyCalled bool
var outpostPartialUpdateCalled, destroyCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
outpostRetrieve: outpostRetrieveHandler(t, []int32{wantPK}),
outpostPartialUpdate: func(w http.ResponseWriter, r *http.Request) {
outpostPartialUpdateCalled = true
var body struct {
Providers []int32 `json:"providers"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatalf("decode outpost patch body: %v", err)
}
if slices.Contains(body.Providers, wantPK) {
t.Fatalf("patched providers = %v, want provider %d removed", body.Providers, wantPK)
}
writeJSON(t, w, http.StatusOK, map[string]any{"pk": testOutpostID, "providers": body.Providers})
},
proxyDestroy: func(w http.ResponseWriter, r *http.Request) {
destroyCalled = true
if r.Method != http.MethodDelete {
@@ -147,6 +232,49 @@ func TestController_syncHandler_delete(t *testing.T) {
if err != nil {
t.Fatalf("syncHandler() error = %v", err)
}
if !outpostPartialUpdateCalled {
t.Fatal("expected Authentik outpost partial update call")
}
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_providerNotInOutpost(t *testing.T) {
now := metav1.Now()
pp := testProxyProvider()
pp.Status.PK = "42"
pp.DeletionTimestamp = &now
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
var outpostPartialUpdateCalled, destroyCalled bool
server := newAuthentikTestServer(t, authentikTestHandlers{
outpostRetrieve: outpostRetrieveHandler(t, nil),
outpostPartialUpdate: func(w http.ResponseWriter, _ *http.Request) {
outpostPartialUpdateCalled = true
},
proxyDestroy: func(w http.ResponseWriter, _ *http.Request) {
destroyCalled = true
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 outpostPartialUpdateCalled {
t.Fatal("did not expect Authentik outpost partial update when provider is not in outpost")
}
if !destroyCalled {
t.Fatal("expected Authentik destroy call")
}
@@ -158,6 +286,7 @@ func TestController_syncHandler_delete(t *testing.T) {
}
func TestController_syncHandler_delete_providerAlreadyGone(t *testing.T) {
const wantPK int32 = 42
now := metav1.Now()
pp := testProxyProvider()
pp.Status.PK = "42"
@@ -165,6 +294,16 @@ func TestController_syncHandler_delete_providerAlreadyGone(t *testing.T) {
pp.Finalizers = []string{DeleteAuthentikProxyProviderFinalizer}
server := newAuthentikTestServer(t, authentikTestHandlers{
outpostRetrieve: outpostRetrieveHandler(t, []int32{wantPK}),
outpostPartialUpdate: func(w http.ResponseWriter, r *http.Request) {
var body struct {
Providers []int32 `json:"providers"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
t.Fatalf("decode outpost patch body: %v", err)
}
writeJSON(t, w, http.StatusOK, map[string]any{"pk": testOutpostID, "providers": body.Providers})
},
proxyDestroy: func(w http.ResponseWriter, _ *http.Request) {
http.NotFound(w, nil)
},
@@ -218,20 +357,6 @@ func TestController_syncHandler_invalidPK(t *testing.T) {
}
}
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 {
@@ -249,11 +374,12 @@ func testProxyProvider() *v1alpha1.ProxyProvider {
AuthorizationFlow: "flow-auth",
InvalidationFlow: "flow-invalidate",
ExternalHost: "https://app.example.com",
Outpost: testOutpostID,
},
}
}
func newTestController(t *testing.T, pp *v1alpha1.ProxyProvider, authentikURL string) (*Controller, context.Context, context.CancelFunc) {
func newTestController(t *testing.T, pp *v1alpha1.ProxyProvider, authentikURL string) (*ProxyProviderController, context.Context, context.CancelFunc) {
t.Helper()
ctx, cancel := context.WithCancel(context.Background())
ctrl, _, stop := newTestControllerWithContext(t, ctx, pp, authentikURL)
@@ -263,7 +389,7 @@ func newTestController(t *testing.T, pp *v1alpha1.ProxyProvider, authentikURL st
}
}
func newTestControllerWithContext(t *testing.T, ctx context.Context, pp *v1alpha1.ProxyProvider, authentikURL string) (*Controller, context.Context, func()) {
func newTestControllerWithContext(t *testing.T, ctx context.Context, pp *v1alpha1.ProxyProvider, authentikURL string) (*ProxyProviderController, context.Context, func()) {
t.Helper()
authentikClient := newAuthentikAPIClientForTest(t, authentikURL)
@@ -309,6 +435,18 @@ type authentikTestHandlers struct {
proxyDestroy http.HandlerFunc
proxyPartialUpdate http.HandlerFunc
allRetrieve http.HandlerFunc
outpostRetrieve http.HandlerFunc
outpostPartialUpdate http.HandlerFunc
}
func outpostRetrieveHandler(t *testing.T, providers []int32) http.HandlerFunc {
t.Helper()
return func(w http.ResponseWriter, _ *http.Request) {
writeJSON(t, w, http.StatusOK, map[string]any{
"pk": testOutpostID,
"providers": providers,
})
}
}
func newAuthentikTestServer(t *testing.T, handlers authentikTestHandlers) *httptest.Server {
@@ -355,6 +493,30 @@ func newAuthentikTestServer(t *testing.T, handlers authentikTestHandlers) *httpt
}
http.NotFound(w, r)
case strings.HasPrefix(path, "/api/v3/outposts/instances/") && strings.HasSuffix(path, "/"):
idPath := strings.TrimPrefix(path, "/api/v3/outposts/instances/")
idPath = strings.TrimSuffix(idPath, "/")
if idPath == "" || strings.Contains(idPath, "/") {
http.NotFound(w, r)
return
}
switch r.Method {
case http.MethodGet:
if handlers.outpostRetrieve != nil {
handlers.outpostRetrieve(w, r)
return
}
http.NotFound(w, r)
case http.MethodPatch:
if handlers.outpostPartialUpdate != nil {
handlers.outpostPartialUpdate(w, r)
return
}
http.NotFound(w, r)
default:
http.Error(w, "unexpected method on outpost instance", http.StatusMethodNotAllowed)
}
default:
http.NotFound(w, r)
}
@@ -372,7 +534,7 @@ func writeJSON(t *testing.T, w http.ResponseWriter, status int, body any) {
}
}
func getProxyProvider(t *testing.T, ctrl *Controller, namespace, name string) *v1alpha1.ProxyProvider {
func getProxyProvider(t *testing.T, ctrl *ProxyProviderController, namespace, name string) *v1alpha1.ProxyProvider {
t.Helper()
got, err := ctrl.proxyProviderClientset.ProxyproviderV1alpha1().ProxyProviders(namespace).Get(
@@ -0,0 +1,243 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// ApplicationApplyConfiguration represents a declarative configuration of the Application type for use
// with apply.
type ApplicationApplyConfiguration struct {
v1.TypeMetaApplyConfiguration `json:""`
*v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
Spec *ApplicationSpecApplyConfiguration `json:"spec,omitempty"`
Status *ApplicationStatusApplyConfiguration `json:"status,omitempty"`
}
// Application constructs a declarative configuration of the Application type for use with
// apply.
func Application(name, namespace string) *ApplicationApplyConfiguration {
b := &ApplicationApplyConfiguration{}
b.WithName(name)
b.WithNamespace(namespace)
b.WithKind("Application")
b.WithAPIVersion("application.t000-n.de/v1alpha1")
return b
}
func (b ApplicationApplyConfiguration) IsApplyConfiguration() {}
// WithKind sets the Kind field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Kind field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithKind(value string) *ApplicationApplyConfiguration {
b.TypeMetaApplyConfiguration.Kind = &value
return b
}
// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the APIVersion field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithAPIVersion(value string) *ApplicationApplyConfiguration {
b.TypeMetaApplyConfiguration.APIVersion = &value
return b
}
// WithName sets the Name field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Name field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithName(value string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Name = &value
return b
}
// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the GenerateName field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithGenerateName(value string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.GenerateName = &value
return b
}
// WithNamespace sets the Namespace field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Namespace field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithNamespace(value string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Namespace = &value
return b
}
// WithUID sets the UID field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UID field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithUID(value types.UID) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.UID = &value
return b
}
// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ResourceVersion field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithResourceVersion(value string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.ResourceVersion = &value
return b
}
// WithGeneration sets the Generation field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Generation field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithGeneration(value int64) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Generation = &value
return b
}
// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CreationTimestamp field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithCreationTimestamp(value metav1.Time) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.CreationTimestamp = &value
return b
}
// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value
return b
}
// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value
return b
}
// WithLabels puts the entries into the Labels field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Labels field,
// overwriting an existing map entries in Labels field with the same key.
func (b *ApplicationApplyConfiguration) WithLabels(entries map[string]string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries))
}
for k, v := range entries {
b.ObjectMetaApplyConfiguration.Labels[k] = v
}
return b
}
// WithAnnotations puts the entries into the Annotations field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Annotations field,
// overwriting an existing map entries in Annotations field with the same key.
func (b *ApplicationApplyConfiguration) WithAnnotations(entries map[string]string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries))
}
for k, v := range entries {
b.ObjectMetaApplyConfiguration.Annotations[k] = v
}
return b
}
// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
func (b *ApplicationApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
if values[i] == nil {
panic("nil value passed to WithOwnerReferences")
}
b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i])
}
return b
}
// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Finalizers field.
func (b *ApplicationApplyConfiguration) WithFinalizers(values ...string) *ApplicationApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i])
}
return b
}
func (b *ApplicationApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
if b.ObjectMetaApplyConfiguration == nil {
b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
}
}
// WithSpec sets the Spec field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Spec field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithSpec(value *ApplicationSpecApplyConfiguration) *ApplicationApplyConfiguration {
b.Spec = value
return b
}
// WithStatus sets the Status field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Status field is set to the value of the last call.
func (b *ApplicationApplyConfiguration) WithStatus(value *ApplicationStatusApplyConfiguration) *ApplicationApplyConfiguration {
b.Status = value
return b
}
// GetKind retrieves the value of the Kind field in the declarative configuration.
func (b *ApplicationApplyConfiguration) GetKind() *string {
return b.TypeMetaApplyConfiguration.Kind
}
// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration.
func (b *ApplicationApplyConfiguration) GetAPIVersion() *string {
return b.TypeMetaApplyConfiguration.APIVersion
}
// GetName retrieves the value of the Name field in the declarative configuration.
func (b *ApplicationApplyConfiguration) GetName() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Name
}
// GetNamespace retrieves the value of the Namespace field in the declarative configuration.
func (b *ApplicationApplyConfiguration) GetNamespace() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Namespace
}
@@ -0,0 +1,57 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1alpha1
// ApplicationSpecApplyConfiguration represents a declarative configuration of the ApplicationSpec type for use
// with apply.
type ApplicationSpecApplyConfiguration struct {
Name *string `json:"name,omitempty"`
Slug *string `json:"slug,omitempty"`
Provider *int32 `json:"provider,omitempty"`
}
// ApplicationSpecApplyConfiguration constructs a declarative configuration of the ApplicationSpec type for use with
// apply.
func ApplicationSpec() *ApplicationSpecApplyConfiguration {
return &ApplicationSpecApplyConfiguration{}
}
// WithName sets the Name field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Name field is set to the value of the last call.
func (b *ApplicationSpecApplyConfiguration) WithName(value string) *ApplicationSpecApplyConfiguration {
b.Name = &value
return b
}
// WithSlug sets the Slug field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Slug field is set to the value of the last call.
func (b *ApplicationSpecApplyConfiguration) WithSlug(value string) *ApplicationSpecApplyConfiguration {
b.Slug = &value
return b
}
// WithProvider sets the Provider field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Provider field is set to the value of the last call.
func (b *ApplicationSpecApplyConfiguration) WithProvider(value int32) *ApplicationSpecApplyConfiguration {
b.Provider = &value
return b
}
@@ -0,0 +1,39 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1alpha1
// ApplicationStatusApplyConfiguration represents a declarative configuration of the ApplicationStatus type for use
// with apply.
type ApplicationStatusApplyConfiguration struct {
PK *string `json:"pk,omitempty"`
}
// ApplicationStatusApplyConfiguration constructs a declarative configuration of the ApplicationStatus type for use with
// apply.
func ApplicationStatus() *ApplicationStatusApplyConfiguration {
return &ApplicationStatusApplyConfiguration{}
}
// WithPK sets the PK field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the PK field is set to the value of the last call.
func (b *ApplicationStatusApplyConfiguration) WithPK(value string) *ApplicationStatusApplyConfiguration {
b.PK = &value
return b
}
@@ -0,0 +1,243 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
v1 "k8s.io/client-go/applyconfigurations/meta/v1"
)
// PolicyBindingApplyConfiguration represents a declarative configuration of the PolicyBinding type for use
// with apply.
type PolicyBindingApplyConfiguration struct {
v1.TypeMetaApplyConfiguration `json:""`
*v1.ObjectMetaApplyConfiguration `json:"metadata,omitempty"`
Spec *PolicyBindingSpecApplyConfiguration `json:"spec,omitempty"`
Status *PolicyBindingStatusApplyConfiguration `json:"status,omitempty"`
}
// PolicyBinding constructs a declarative configuration of the PolicyBinding type for use with
// apply.
func PolicyBinding(name, namespace string) *PolicyBindingApplyConfiguration {
b := &PolicyBindingApplyConfiguration{}
b.WithName(name)
b.WithNamespace(namespace)
b.WithKind("PolicyBinding")
b.WithAPIVersion("policybinding.t000-n.de/v1alpha1")
return b
}
func (b PolicyBindingApplyConfiguration) IsApplyConfiguration() {}
// WithKind sets the Kind field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Kind field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithKind(value string) *PolicyBindingApplyConfiguration {
b.TypeMetaApplyConfiguration.Kind = &value
return b
}
// WithAPIVersion sets the APIVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the APIVersion field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithAPIVersion(value string) *PolicyBindingApplyConfiguration {
b.TypeMetaApplyConfiguration.APIVersion = &value
return b
}
// WithName sets the Name field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Name field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithName(value string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Name = &value
return b
}
// WithGenerateName sets the GenerateName field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the GenerateName field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithGenerateName(value string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.GenerateName = &value
return b
}
// WithNamespace sets the Namespace field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Namespace field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithNamespace(value string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Namespace = &value
return b
}
// WithUID sets the UID field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the UID field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithUID(value types.UID) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.UID = &value
return b
}
// WithResourceVersion sets the ResourceVersion field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the ResourceVersion field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithResourceVersion(value string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.ResourceVersion = &value
return b
}
// WithGeneration sets the Generation field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Generation field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithGeneration(value int64) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.Generation = &value
return b
}
// WithCreationTimestamp sets the CreationTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the CreationTimestamp field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithCreationTimestamp(value metav1.Time) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.CreationTimestamp = &value
return b
}
// WithDeletionTimestamp sets the DeletionTimestamp field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionTimestamp field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithDeletionTimestamp(value metav1.Time) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionTimestamp = &value
return b
}
// WithDeletionGracePeriodSeconds sets the DeletionGracePeriodSeconds field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the DeletionGracePeriodSeconds field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithDeletionGracePeriodSeconds(value int64) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
b.ObjectMetaApplyConfiguration.DeletionGracePeriodSeconds = &value
return b
}
// WithLabels puts the entries into the Labels field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Labels field,
// overwriting an existing map entries in Labels field with the same key.
func (b *PolicyBindingApplyConfiguration) WithLabels(entries map[string]string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Labels == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Labels = make(map[string]string, len(entries))
}
for k, v := range entries {
b.ObjectMetaApplyConfiguration.Labels[k] = v
}
return b
}
// WithAnnotations puts the entries into the Annotations field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, the entries provided by each call will be put on the Annotations field,
// overwriting an existing map entries in Annotations field with the same key.
func (b *PolicyBindingApplyConfiguration) WithAnnotations(entries map[string]string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
if b.ObjectMetaApplyConfiguration.Annotations == nil && len(entries) > 0 {
b.ObjectMetaApplyConfiguration.Annotations = make(map[string]string, len(entries))
}
for k, v := range entries {
b.ObjectMetaApplyConfiguration.Annotations[k] = v
}
return b
}
// WithOwnerReferences adds the given value to the OwnerReferences field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the OwnerReferences field.
func (b *PolicyBindingApplyConfiguration) WithOwnerReferences(values ...*v1.OwnerReferenceApplyConfiguration) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
if values[i] == nil {
panic("nil value passed to WithOwnerReferences")
}
b.ObjectMetaApplyConfiguration.OwnerReferences = append(b.ObjectMetaApplyConfiguration.OwnerReferences, *values[i])
}
return b
}
// WithFinalizers adds the given value to the Finalizers field in the declarative configuration
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
// If called multiple times, values provided by each call will be appended to the Finalizers field.
func (b *PolicyBindingApplyConfiguration) WithFinalizers(values ...string) *PolicyBindingApplyConfiguration {
b.ensureObjectMetaApplyConfigurationExists()
for i := range values {
b.ObjectMetaApplyConfiguration.Finalizers = append(b.ObjectMetaApplyConfiguration.Finalizers, values[i])
}
return b
}
func (b *PolicyBindingApplyConfiguration) ensureObjectMetaApplyConfigurationExists() {
if b.ObjectMetaApplyConfiguration == nil {
b.ObjectMetaApplyConfiguration = &v1.ObjectMetaApplyConfiguration{}
}
}
// WithSpec sets the Spec field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Spec field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithSpec(value *PolicyBindingSpecApplyConfiguration) *PolicyBindingApplyConfiguration {
b.Spec = value
return b
}
// WithStatus sets the Status field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Status field is set to the value of the last call.
func (b *PolicyBindingApplyConfiguration) WithStatus(value *PolicyBindingStatusApplyConfiguration) *PolicyBindingApplyConfiguration {
b.Status = value
return b
}
// GetKind retrieves the value of the Kind field in the declarative configuration.
func (b *PolicyBindingApplyConfiguration) GetKind() *string {
return b.TypeMetaApplyConfiguration.Kind
}
// GetAPIVersion retrieves the value of the APIVersion field in the declarative configuration.
func (b *PolicyBindingApplyConfiguration) GetAPIVersion() *string {
return b.TypeMetaApplyConfiguration.APIVersion
}
// GetName retrieves the value of the Name field in the declarative configuration.
func (b *PolicyBindingApplyConfiguration) GetName() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Name
}
// GetNamespace retrieves the value of the Namespace field in the declarative configuration.
func (b *PolicyBindingApplyConfiguration) GetNamespace() *string {
b.ensureObjectMetaApplyConfigurationExists()
return b.ObjectMetaApplyConfiguration.Namespace
}
@@ -0,0 +1,75 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1alpha1
// PolicyBindingSpecApplyConfiguration represents a declarative configuration of the PolicyBindingSpec type for use
// with apply.
type PolicyBindingSpecApplyConfiguration struct {
Policy *string `json:"policy,omitempty"`
Group *string `json:"group,omitempty"`
User *int32 `json:"user,omitempty"`
Target *string `json:"target,omitempty"`
Order *int32 `json:"order,omitempty"`
}
// PolicyBindingSpecApplyConfiguration constructs a declarative configuration of the PolicyBindingSpec type for use with
// apply.
func PolicyBindingSpec() *PolicyBindingSpecApplyConfiguration {
return &PolicyBindingSpecApplyConfiguration{}
}
// WithPolicy sets the Policy field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Policy field is set to the value of the last call.
func (b *PolicyBindingSpecApplyConfiguration) WithPolicy(value string) *PolicyBindingSpecApplyConfiguration {
b.Policy = &value
return b
}
// WithGroup sets the Group field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Group field is set to the value of the last call.
func (b *PolicyBindingSpecApplyConfiguration) WithGroup(value string) *PolicyBindingSpecApplyConfiguration {
b.Group = &value
return b
}
// WithUser sets the User field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the User field is set to the value of the last call.
func (b *PolicyBindingSpecApplyConfiguration) WithUser(value int32) *PolicyBindingSpecApplyConfiguration {
b.User = &value
return b
}
// WithTarget sets the Target field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Target field is set to the value of the last call.
func (b *PolicyBindingSpecApplyConfiguration) WithTarget(value string) *PolicyBindingSpecApplyConfiguration {
b.Target = &value
return b
}
// WithOrder sets the Order field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Order field is set to the value of the last call.
func (b *PolicyBindingSpecApplyConfiguration) WithOrder(value int32) *PolicyBindingSpecApplyConfiguration {
b.Order = &value
return b
}
@@ -0,0 +1,39 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by applyconfiguration-gen. DO NOT EDIT.
package v1alpha1
// PolicyBindingStatusApplyConfiguration represents a declarative configuration of the PolicyBindingStatus type for use
// with apply.
type PolicyBindingStatusApplyConfiguration struct {
PK *string `json:"pk,omitempty"`
}
// PolicyBindingStatusApplyConfiguration constructs a declarative configuration of the PolicyBindingStatus type for use with
// apply.
func PolicyBindingStatus() *PolicyBindingStatusApplyConfiguration {
return &PolicyBindingStatusApplyConfiguration{}
}
// WithPK sets the PK field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the PK field is set to the value of the last call.
func (b *PolicyBindingStatusApplyConfiguration) WithPK(value string) *PolicyBindingStatusApplyConfiguration {
b.PK = &value
return b
}
@@ -25,6 +25,7 @@ type ProxyProviderSpecApplyConfiguration struct {
AuthorizationFlow *string `json:"authorization_flow,omitempty"`
InvalidationFlow *string `json:"invalidation_flow,omitempty"`
ExternalHost *string `json:"external_host,omitempty"`
Outpost *string `json:"outpost,omitempty"`
}
// ProxyProviderSpecApplyConfiguration constructs a declarative configuration of the ProxyProviderSpec type for use with
@@ -64,3 +65,11 @@ func (b *ProxyProviderSpecApplyConfiguration) WithExternalHost(value string) *Pr
b.ExternalHost = &value
return b
}
// WithOutpost sets the Outpost field in the declarative configuration to the given value
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
// If called multiple times, the Outpost field is set to the value of the last call.
func (b *ProxyProviderSpecApplyConfiguration) WithOutpost(value string) *ProxyProviderSpecApplyConfiguration {
b.Outpost = &value
return b
}
+28 -8
View File
@@ -19,9 +19,13 @@ limitations under the License.
package applyconfiguration
import (
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/application/v1alpha1"
internal "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/internal"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/proxyprovider/v1alpha1"
applyconfigurationpolicybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/policybinding/v1alpha1"
applyconfigurationproxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/proxyprovider/v1alpha1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
@@ -31,13 +35,29 @@ import (
// apply configuration type exists for the given GroupVersionKind.
func ForKind(kind schema.GroupVersionKind) interface{} {
switch kind {
// Group=application.t000-n.de, Version=v1alpha1
case v1alpha1.SchemeGroupVersion.WithKind("Application"):
return &applicationv1alpha1.ApplicationApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("ApplicationSpec"):
return &applicationv1alpha1.ApplicationSpecApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("ApplicationStatus"):
return &applicationv1alpha1.ApplicationStatusApplyConfiguration{}
// Group=policybinding.t000-n.de, Version=v1alpha1
case policybindingv1alpha1.SchemeGroupVersion.WithKind("PolicyBinding"):
return &applyconfigurationpolicybindingv1alpha1.PolicyBindingApplyConfiguration{}
case policybindingv1alpha1.SchemeGroupVersion.WithKind("PolicyBindingSpec"):
return &applyconfigurationpolicybindingv1alpha1.PolicyBindingSpecApplyConfiguration{}
case policybindingv1alpha1.SchemeGroupVersion.WithKind("PolicyBindingStatus"):
return &applyconfigurationpolicybindingv1alpha1.PolicyBindingStatusApplyConfiguration{}
// Group=proxyprovider.t000-n.de, Version=v1alpha1
case v1alpha1.SchemeGroupVersion.WithKind("ProxyProvider"):
return &proxyproviderv1alpha1.ProxyProviderApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("ProxyProviderSpec"):
return &proxyproviderv1alpha1.ProxyProviderSpecApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("ProxyProviderStatus"):
return &proxyproviderv1alpha1.ProxyProviderStatusApplyConfiguration{}
case proxyproviderv1alpha1.SchemeGroupVersion.WithKind("ProxyProvider"):
return &applyconfigurationproxyproviderv1alpha1.ProxyProviderApplyConfiguration{}
case proxyproviderv1alpha1.SchemeGroupVersion.WithKind("ProxyProviderSpec"):
return &applyconfigurationproxyproviderv1alpha1.ProxyProviderSpecApplyConfiguration{}
case proxyproviderv1alpha1.SchemeGroupVersion.WithKind("ProxyProviderStatus"):
return &applyconfigurationproxyproviderv1alpha1.ProxyProviderStatusApplyConfiguration{}
}
return nil
@@ -22,6 +22,8 @@ import (
fmt "fmt"
http "net/http"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/application/v1alpha1"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/policybinding/v1alpha1"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/proxyprovider/v1alpha1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
@@ -30,15 +32,29 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
ApplicationV1alpha1() applicationv1alpha1.ApplicationV1alpha1Interface
PolicyBindingV1alpha1() policybindingv1alpha1.PolicyBindingV1alpha1Interface
ProxyproviderV1alpha1() proxyproviderv1alpha1.ProxyproviderV1alpha1Interface
}
// Clientset contains the clients for groups.
type Clientset struct {
*discovery.DiscoveryClient
applicationV1alpha1 *applicationv1alpha1.ApplicationV1alpha1Client
policyBindingV1alpha1 *policybindingv1alpha1.PolicyBindingV1alpha1Client
proxyproviderV1alpha1 *proxyproviderv1alpha1.ProxyproviderV1alpha1Client
}
// ApplicationV1alpha1 retrieves the ApplicationV1alpha1Client
func (c *Clientset) ApplicationV1alpha1() applicationv1alpha1.ApplicationV1alpha1Interface {
return c.applicationV1alpha1
}
// PolicyBindingV1alpha1 retrieves the PolicyBindingV1alpha1Client
func (c *Clientset) PolicyBindingV1alpha1() policybindingv1alpha1.PolicyBindingV1alpha1Interface {
return c.policyBindingV1alpha1
}
// ProxyproviderV1alpha1 retrieves the ProxyproviderV1alpha1Client
func (c *Clientset) ProxyproviderV1alpha1() proxyproviderv1alpha1.ProxyproviderV1alpha1Interface {
return c.proxyproviderV1alpha1
@@ -88,6 +104,14 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset,
var cs Clientset
var err error
cs.applicationV1alpha1, err = applicationv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
cs.policyBindingV1alpha1, err = policybindingv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
cs.proxyproviderV1alpha1, err = proxyproviderv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
@@ -113,6 +137,8 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
// New creates a new Clientset for the given RESTClient.
func New(c rest.Interface) *Clientset {
var cs Clientset
cs.applicationV1alpha1 = applicationv1alpha1.New(c)
cs.policyBindingV1alpha1 = policybindingv1alpha1.New(c)
cs.proxyproviderV1alpha1 = proxyproviderv1alpha1.New(c)
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
@@ -21,6 +21,10 @@ package fake
import (
applyconfiguration "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration"
clientset "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/application/v1alpha1"
fakeapplicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/application/v1alpha1/fake"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/policybinding/v1alpha1"
fakepolicybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/policybinding/v1alpha1/fake"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/proxyprovider/v1alpha1"
fakeproxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/proxyprovider/v1alpha1/fake"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -136,6 +140,16 @@ var (
_ testing.FakeClient = &Clientset{}
)
// ApplicationV1alpha1 retrieves the ApplicationV1alpha1Client
func (c *Clientset) ApplicationV1alpha1() applicationv1alpha1.ApplicationV1alpha1Interface {
return &fakeapplicationv1alpha1.FakeApplicationV1alpha1{Fake: &c.Fake}
}
// PolicyBindingV1alpha1 retrieves the PolicyBindingV1alpha1Client
func (c *Clientset) PolicyBindingV1alpha1() policybindingv1alpha1.PolicyBindingV1alpha1Interface {
return &fakepolicybindingv1alpha1.FakePolicyBindingV1alpha1{Fake: &c.Fake}
}
// ProxyproviderV1alpha1 retrieves the ProxyproviderV1alpha1Client
func (c *Clientset) ProxyproviderV1alpha1() proxyproviderv1alpha1.ProxyproviderV1alpha1Interface {
return &fakeproxyproviderv1alpha1.FakeProxyproviderV1alpha1{Fake: &c.Fake}
@@ -19,6 +19,8 @@ limitations under the License.
package fake
import (
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@@ -31,6 +33,8 @@ var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
applicationv1alpha1.AddToScheme,
policybindingv1alpha1.AddToScheme,
proxyproviderv1alpha1.AddToScheme,
}
@@ -19,6 +19,8 @@ limitations under the License.
package scheme
import (
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@@ -31,6 +33,8 @@ var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
applicationv1alpha1.AddToScheme,
policybindingv1alpha1.AddToScheme,
proxyproviderv1alpha1.AddToScheme,
}
@@ -0,0 +1,74 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
context "context"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
applyconfigurationapplicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/application/v1alpha1"
scheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
gentype "k8s.io/client-go/gentype"
)
// ApplicationsGetter has a method to return a ApplicationInterface.
// A group's client should implement this interface.
type ApplicationsGetter interface {
Applications(namespace string) ApplicationInterface
}
// ApplicationInterface has methods to work with Application resources.
type ApplicationInterface interface {
Create(ctx context.Context, application *applicationv1alpha1.Application, opts v1.CreateOptions) (*applicationv1alpha1.Application, error)
Update(ctx context.Context, application *applicationv1alpha1.Application, opts v1.UpdateOptions) (*applicationv1alpha1.Application, error)
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
UpdateStatus(ctx context.Context, application *applicationv1alpha1.Application, opts v1.UpdateOptions) (*applicationv1alpha1.Application, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*applicationv1alpha1.Application, error)
List(ctx context.Context, opts v1.ListOptions) (*applicationv1alpha1.ApplicationList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *applicationv1alpha1.Application, err error)
Apply(ctx context.Context, application *applyconfigurationapplicationv1alpha1.ApplicationApplyConfiguration, opts v1.ApplyOptions) (result *applicationv1alpha1.Application, err error)
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
ApplyStatus(ctx context.Context, application *applyconfigurationapplicationv1alpha1.ApplicationApplyConfiguration, opts v1.ApplyOptions) (result *applicationv1alpha1.Application, err error)
ApplicationExpansion
}
// applications implements ApplicationInterface
type applications struct {
*gentype.ClientWithListAndApply[*applicationv1alpha1.Application, *applicationv1alpha1.ApplicationList, *applyconfigurationapplicationv1alpha1.ApplicationApplyConfiguration]
}
// newApplications returns a Applications
func newApplications(c *ApplicationV1alpha1Client, namespace string) *applications {
return &applications{
gentype.NewClientWithListAndApply[*applicationv1alpha1.Application, *applicationv1alpha1.ApplicationList, *applyconfigurationapplicationv1alpha1.ApplicationApplyConfiguration](
"applications",
c.RESTClient(),
scheme.ParameterCodec,
namespace,
func() *applicationv1alpha1.Application { return &applicationv1alpha1.Application{} },
func() *applicationv1alpha1.ApplicationList { return &applicationv1alpha1.ApplicationList{} },
),
}
}
@@ -0,0 +1,101 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
http "net/http"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
scheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type ApplicationV1alpha1Interface interface {
RESTClient() rest.Interface
ApplicationsGetter
}
// ApplicationV1alpha1Client is used to interact with features provided by the application.t000-n.de group.
type ApplicationV1alpha1Client struct {
restClient rest.Interface
}
func (c *ApplicationV1alpha1Client) Applications(namespace string) ApplicationInterface {
return newApplications(c, namespace)
}
// NewForConfig creates a new ApplicationV1alpha1Client for the given config.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*ApplicationV1alpha1Client, error) {
config := *c
setConfigDefaults(&config)
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&config, httpClient)
}
// NewForConfigAndClient creates a new ApplicationV1alpha1Client for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ApplicationV1alpha1Client, error) {
config := *c
setConfigDefaults(&config)
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
}
return &ApplicationV1alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new ApplicationV1alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *ApplicationV1alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new ApplicationV1alpha1Client for the given RESTClient.
func New(c rest.Interface) *ApplicationV1alpha1Client {
return &ApplicationV1alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) {
gv := applicationv1alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *ApplicationV1alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}
@@ -0,0 +1,20 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v1alpha1
@@ -0,0 +1,20 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake
@@ -0,0 +1,53 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/application/v1alpha1"
typedapplicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/application/v1alpha1"
gentype "k8s.io/client-go/gentype"
)
// fakeApplications implements ApplicationInterface
type fakeApplications struct {
*gentype.FakeClientWithListAndApply[*v1alpha1.Application, *v1alpha1.ApplicationList, *applicationv1alpha1.ApplicationApplyConfiguration]
Fake *FakeApplicationV1alpha1
}
func newFakeApplications(fake *FakeApplicationV1alpha1, namespace string) typedapplicationv1alpha1.ApplicationInterface {
return &fakeApplications{
gentype.NewFakeClientWithListAndApply[*v1alpha1.Application, *v1alpha1.ApplicationList, *applicationv1alpha1.ApplicationApplyConfiguration](
fake.Fake,
namespace,
v1alpha1.SchemeGroupVersion.WithResource("applications"),
v1alpha1.SchemeGroupVersion.WithKind("Application"),
func() *v1alpha1.Application { return &v1alpha1.Application{} },
func() *v1alpha1.ApplicationList { return &v1alpha1.ApplicationList{} },
func(dst, src *v1alpha1.ApplicationList) { dst.ListMeta = src.ListMeta },
func(list *v1alpha1.ApplicationList) []*v1alpha1.Application {
return gentype.ToPointerSlice(list.Items)
},
func(list *v1alpha1.ApplicationList, items []*v1alpha1.Application) {
list.Items = gentype.FromPointerSlice(items)
},
),
fake,
}
}
@@ -0,0 +1,40 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/application/v1alpha1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeApplicationV1alpha1 struct {
*testing.Fake
}
func (c *FakeApplicationV1alpha1) Applications(namespace string) v1alpha1.ApplicationInterface {
return newFakeApplications(c, namespace)
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeApplicationV1alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}
@@ -0,0 +1,21 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
type ApplicationExpansion interface{}
@@ -0,0 +1,20 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// This package has the automatically generated typed clients.
package v1alpha1
@@ -0,0 +1,20 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
// Package fake has the automatically generated clients.
package fake
@@ -0,0 +1,53 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/policybinding/v1alpha1"
typedpolicybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/policybinding/v1alpha1"
gentype "k8s.io/client-go/gentype"
)
// fakePolicyBindings implements PolicyBindingInterface
type fakePolicyBindings struct {
*gentype.FakeClientWithListAndApply[*v1alpha1.PolicyBinding, *v1alpha1.PolicyBindingList, *policybindingv1alpha1.PolicyBindingApplyConfiguration]
Fake *FakePolicyBindingV1alpha1
}
func newFakePolicyBindings(fake *FakePolicyBindingV1alpha1, namespace string) typedpolicybindingv1alpha1.PolicyBindingInterface {
return &fakePolicyBindings{
gentype.NewFakeClientWithListAndApply[*v1alpha1.PolicyBinding, *v1alpha1.PolicyBindingList, *policybindingv1alpha1.PolicyBindingApplyConfiguration](
fake.Fake,
namespace,
v1alpha1.SchemeGroupVersion.WithResource("policybindings"),
v1alpha1.SchemeGroupVersion.WithKind("PolicyBinding"),
func() *v1alpha1.PolicyBinding { return &v1alpha1.PolicyBinding{} },
func() *v1alpha1.PolicyBindingList { return &v1alpha1.PolicyBindingList{} },
func(dst, src *v1alpha1.PolicyBindingList) { dst.ListMeta = src.ListMeta },
func(list *v1alpha1.PolicyBindingList) []*v1alpha1.PolicyBinding {
return gentype.ToPointerSlice(list.Items)
},
func(list *v1alpha1.PolicyBindingList, items []*v1alpha1.PolicyBinding) {
list.Items = gentype.FromPointerSlice(items)
},
),
fake,
}
}
@@ -0,0 +1,40 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/typed/policybinding/v1alpha1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakePolicyBindingV1alpha1 struct {
*testing.Fake
}
func (c *FakePolicyBindingV1alpha1) PolicyBindings(namespace string) v1alpha1.PolicyBindingInterface {
return newFakePolicyBindings(c, namespace)
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakePolicyBindingV1alpha1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}
@@ -0,0 +1,21 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
type PolicyBindingExpansion interface{}
@@ -0,0 +1,74 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
context "context"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
applyconfigurationpolicybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/applyconfiguration/policybinding/v1alpha1"
scheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
gentype "k8s.io/client-go/gentype"
)
// PolicyBindingsGetter has a method to return a PolicyBindingInterface.
// A group's client should implement this interface.
type PolicyBindingsGetter interface {
PolicyBindings(namespace string) PolicyBindingInterface
}
// PolicyBindingInterface has methods to work with PolicyBinding resources.
type PolicyBindingInterface interface {
Create(ctx context.Context, policyBinding *policybindingv1alpha1.PolicyBinding, opts v1.CreateOptions) (*policybindingv1alpha1.PolicyBinding, error)
Update(ctx context.Context, policyBinding *policybindingv1alpha1.PolicyBinding, opts v1.UpdateOptions) (*policybindingv1alpha1.PolicyBinding, error)
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
UpdateStatus(ctx context.Context, policyBinding *policybindingv1alpha1.PolicyBinding, opts v1.UpdateOptions) (*policybindingv1alpha1.PolicyBinding, error)
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
Get(ctx context.Context, name string, opts v1.GetOptions) (*policybindingv1alpha1.PolicyBinding, error)
List(ctx context.Context, opts v1.ListOptions) (*policybindingv1alpha1.PolicyBindingList, error)
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *policybindingv1alpha1.PolicyBinding, err error)
Apply(ctx context.Context, policyBinding *applyconfigurationpolicybindingv1alpha1.PolicyBindingApplyConfiguration, opts v1.ApplyOptions) (result *policybindingv1alpha1.PolicyBinding, err error)
// Add a +genclient:noStatus comment above the type to avoid generating ApplyStatus().
ApplyStatus(ctx context.Context, policyBinding *applyconfigurationpolicybindingv1alpha1.PolicyBindingApplyConfiguration, opts v1.ApplyOptions) (result *policybindingv1alpha1.PolicyBinding, err error)
PolicyBindingExpansion
}
// policyBindings implements PolicyBindingInterface
type policyBindings struct {
*gentype.ClientWithListAndApply[*policybindingv1alpha1.PolicyBinding, *policybindingv1alpha1.PolicyBindingList, *applyconfigurationpolicybindingv1alpha1.PolicyBindingApplyConfiguration]
}
// newPolicyBindings returns a PolicyBindings
func newPolicyBindings(c *PolicyBindingV1alpha1Client, namespace string) *policyBindings {
return &policyBindings{
gentype.NewClientWithListAndApply[*policybindingv1alpha1.PolicyBinding, *policybindingv1alpha1.PolicyBindingList, *applyconfigurationpolicybindingv1alpha1.PolicyBindingApplyConfiguration](
"policybindings",
c.RESTClient(),
scheme.ParameterCodec,
namespace,
func() *policybindingv1alpha1.PolicyBinding { return &policybindingv1alpha1.PolicyBinding{} },
func() *policybindingv1alpha1.PolicyBindingList { return &policybindingv1alpha1.PolicyBindingList{} },
),
}
}
@@ -0,0 +1,101 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
import (
http "net/http"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
scheme "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned/scheme"
rest "k8s.io/client-go/rest"
)
type PolicyBindingV1alpha1Interface interface {
RESTClient() rest.Interface
PolicyBindingsGetter
}
// PolicyBindingV1alpha1Client is used to interact with features provided by the policybinding.t000-n.de group.
type PolicyBindingV1alpha1Client struct {
restClient rest.Interface
}
func (c *PolicyBindingV1alpha1Client) PolicyBindings(namespace string) PolicyBindingInterface {
return newPolicyBindings(c, namespace)
}
// NewForConfig creates a new PolicyBindingV1alpha1Client for the given config.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*PolicyBindingV1alpha1Client, error) {
config := *c
setConfigDefaults(&config)
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&config, httpClient)
}
// NewForConfigAndClient creates a new PolicyBindingV1alpha1Client for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*PolicyBindingV1alpha1Client, error) {
config := *c
setConfigDefaults(&config)
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
}
return &PolicyBindingV1alpha1Client{client}, nil
}
// NewForConfigOrDie creates a new PolicyBindingV1alpha1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *PolicyBindingV1alpha1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new PolicyBindingV1alpha1Client for the given RESTClient.
func New(c rest.Interface) *PolicyBindingV1alpha1Client {
return &PolicyBindingV1alpha1Client{c}
}
func setConfigDefaults(config *rest.Config) {
gv := policybindingv1alpha1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *PolicyBindingV1alpha1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}
@@ -0,0 +1,46 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package application
import (
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/application/v1alpha1"
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha1 provides access to shared informers for resources in V1alpha1.
V1alpha1() v1alpha1.Interface
}
type group struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha1 returns a new v1alpha1.Interface.
func (g *group) V1alpha1() v1alpha1.Interface {
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}
@@ -0,0 +1,116 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
context "context"
time "time"
apisapplicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
versioned "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/listers/application/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// ApplicationInformer provides access to a shared informer and lister for
// Applications.
type ApplicationInformer interface {
Informer() cache.SharedIndexInformer
Lister() applicationv1alpha1.ApplicationLister
}
type applicationInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewApplicationInformer constructs a new informer for Application type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewApplicationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewApplicationInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers})
}
// NewFilteredApplicationInformer constructs a new informer for Application type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredApplicationInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return NewApplicationInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions})
}
// NewApplicationInformerWithOptions constructs a new informer for Application type with additional options.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewApplicationInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "application.t000-n.de", Version: "v1alpha1", Resource: "applications"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
ListFunc: func(opts v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.ApplicationV1alpha1().Applications(namespace).List(context.Background(), opts)
},
WatchFunc: func(opts v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.ApplicationV1alpha1().Applications(namespace).Watch(context.Background(), opts)
},
ListWithContextFunc: func(ctx context.Context, opts v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.ApplicationV1alpha1().Applications(namespace).List(ctx, opts)
},
WatchFuncWithContext: func(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.ApplicationV1alpha1().Applications(namespace).Watch(ctx, opts)
},
}, client),
&apisapplicationv1alpha1.Application{},
cache.SharedIndexInformerOptions{
ResyncPeriod: options.ResyncPeriod,
Indexers: options.Indexers,
Identifier: identifier,
},
)
}
func (f *applicationInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewApplicationInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions})
}
func (f *applicationInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&apisapplicationv1alpha1.Application{}, f.defaultInformer)
}
func (f *applicationInformer) Lister() applicationv1alpha1.ApplicationLister {
return applicationv1alpha1.NewApplicationLister(f.Informer().GetIndexer())
}
@@ -0,0 +1,45 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// Applications returns a ApplicationInformer.
Applications() ApplicationInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// Applications returns a ApplicationInformer.
func (v *version) Applications() ApplicationInformer {
return &applicationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
@@ -25,7 +25,9 @@ import (
time "time"
versioned "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
application "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/application"
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
policybinding "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/policybinding"
proxyprovider "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/proxyprovider"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
@@ -325,9 +327,19 @@ type SharedInformerFactory interface {
// client.
InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer
Application() application.Interface
PolicyBinding() policybinding.Interface
Proxyprovider() proxyprovider.Interface
}
func (f *sharedInformerFactory) Application() application.Interface {
return application.New(f, f.namespace, f.tweakListOptions)
}
func (f *sharedInformerFactory) PolicyBinding() policybinding.Interface {
return policybinding.New(f, f.namespace, f.tweakListOptions)
}
func (f *sharedInformerFactory) Proxyprovider() proxyprovider.Interface {
return proxyprovider.New(f, f.namespace, f.tweakListOptions)
}
@@ -21,7 +21,9 @@ package externalversions
import (
fmt "fmt"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
proxyproviderv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1"
schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache"
)
@@ -52,8 +54,16 @@ func (f *genericInformer) Lister() cache.GenericLister {
// TODO extend this to unknown resources with a client pool
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
switch resource {
// Group=application.t000-n.de, Version=v1alpha1
case v1alpha1.SchemeGroupVersion.WithResource("applications"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Application().V1alpha1().Applications().Informer()}, nil
// Group=policybinding.t000-n.de, Version=v1alpha1
case policybindingv1alpha1.SchemeGroupVersion.WithResource("policybindings"):
return &genericInformer{resource: resource.GroupResource(), informer: f.PolicyBinding().V1alpha1().PolicyBindings().Informer()}, nil
// Group=proxyprovider.t000-n.de, Version=v1alpha1
case v1alpha1.SchemeGroupVersion.WithResource("proxyproviders"):
case proxyproviderv1alpha1.SchemeGroupVersion.WithResource("proxyproviders"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Proxyprovider().V1alpha1().ProxyProviders().Informer()}, nil
}
@@ -0,0 +1,46 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package policybinding
import (
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
v1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/policybinding/v1alpha1"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha1 provides access to shared informers for resources in V1alpha1.
V1alpha1() v1alpha1.Interface
}
type group struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha1 returns a new v1alpha1.Interface.
func (g *group) V1alpha1() v1alpha1.Interface {
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
}
@@ -0,0 +1,45 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// PolicyBindings returns a PolicyBindingInformer.
PolicyBindings() PolicyBindingInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// PolicyBindings returns a PolicyBindingInformer.
func (v *version) PolicyBindings() PolicyBindingInformer {
return &policyBindingInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
@@ -0,0 +1,116 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha1
import (
context "context"
time "time"
apispolicybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
versioned "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/clientset/versioned"
internalinterfaces "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/informers/externalversions/internalinterfaces"
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/generated/listers/policybinding/v1alpha1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
)
// PolicyBindingInformer provides access to a shared informer and lister for
// PolicyBindings.
type PolicyBindingInformer interface {
Informer() cache.SharedIndexInformer
Lister() policybindingv1alpha1.PolicyBindingLister
}
type policyBindingInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewPolicyBindingInformer constructs a new informer for PolicyBinding type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPolicyBindingInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewPolicyBindingInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers})
}
// NewFilteredPolicyBindingInformer constructs a new informer for PolicyBinding type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredPolicyBindingInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return NewPolicyBindingInformerWithOptions(client, namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: indexers, TweakListOptions: tweakListOptions})
}
// NewPolicyBindingInformerWithOptions constructs a new informer for PolicyBinding type with additional options.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPolicyBindingInformerWithOptions(client versioned.Interface, namespace string, options internalinterfaces.InformerOptions) cache.SharedIndexInformer {
gvr := schema.GroupVersionResource{Group: "policybinding.t000-n.de", Version: "v1alpha1", Resource: "policybindings"}
identifier := options.InformerName.WithResource(gvr)
tweakListOptions := options.TweakListOptions
return cache.NewSharedIndexInformerWithOptions(
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
ListFunc: func(opts v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.PolicyBindingV1alpha1().PolicyBindings(namespace).List(context.Background(), opts)
},
WatchFunc: func(opts v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.PolicyBindingV1alpha1().PolicyBindings(namespace).Watch(context.Background(), opts)
},
ListWithContextFunc: func(ctx context.Context, opts v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.PolicyBindingV1alpha1().PolicyBindings(namespace).List(ctx, opts)
},
WatchFuncWithContext: func(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&opts)
}
return client.PolicyBindingV1alpha1().PolicyBindings(namespace).Watch(ctx, opts)
},
}, client),
&apispolicybindingv1alpha1.PolicyBinding{},
cache.SharedIndexInformerOptions{
ResyncPeriod: options.ResyncPeriod,
Indexers: options.Indexers,
Identifier: identifier,
},
)
}
func (f *policyBindingInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewPolicyBindingInformerWithOptions(client, f.namespace, internalinterfaces.InformerOptions{ResyncPeriod: resyncPeriod, Indexers: cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, InformerName: f.factory.InformerName(), TweakListOptions: f.tweakListOptions})
}
func (f *policyBindingInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&apispolicybindingv1alpha1.PolicyBinding{}, f.defaultInformer)
}
func (f *policyBindingInformer) Lister() policybindingv1alpha1.PolicyBindingLister {
return policybindingv1alpha1.NewPolicyBindingLister(f.Informer().GetIndexer())
}
@@ -0,0 +1,70 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
import (
applicationv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1"
labels "k8s.io/apimachinery/pkg/labels"
listers "k8s.io/client-go/listers"
cache "k8s.io/client-go/tools/cache"
)
// ApplicationLister helps list Applications.
// All objects returned here must be treated as read-only.
type ApplicationLister interface {
// List lists all Applications in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*applicationv1alpha1.Application, err error)
// Applications returns an object that can list and get Applications.
Applications(namespace string) ApplicationNamespaceLister
ApplicationListerExpansion
}
// applicationLister implements the ApplicationLister interface.
type applicationLister struct {
listers.ResourceIndexer[*applicationv1alpha1.Application]
}
// NewApplicationLister returns a new ApplicationLister.
func NewApplicationLister(indexer cache.Indexer) ApplicationLister {
return &applicationLister{listers.New[*applicationv1alpha1.Application](indexer, applicationv1alpha1.Resource("application"))}
}
// Applications returns an object that can list and get Applications.
func (s *applicationLister) Applications(namespace string) ApplicationNamespaceLister {
return applicationNamespaceLister{listers.NewNamespaced[*applicationv1alpha1.Application](s.ResourceIndexer, namespace)}
}
// ApplicationNamespaceLister helps list and get Applications.
// All objects returned here must be treated as read-only.
type ApplicationNamespaceLister interface {
// List lists all Applications in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*applicationv1alpha1.Application, err error)
// Get retrieves the Application from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*applicationv1alpha1.Application, error)
ApplicationNamespaceListerExpansion
}
// applicationNamespaceLister implements the ApplicationNamespaceLister
// interface.
type applicationNamespaceLister struct {
listers.ResourceIndexer[*applicationv1alpha1.Application]
}
@@ -0,0 +1,27 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
// ApplicationListerExpansion allows custom methods to be added to
// ApplicationLister.
type ApplicationListerExpansion interface{}
// ApplicationNamespaceListerExpansion allows custom methods to be added to
// ApplicationNamespaceLister.
type ApplicationNamespaceListerExpansion interface{}
@@ -0,0 +1,27 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
// PolicyBindingListerExpansion allows custom methods to be added to
// PolicyBindingLister.
type PolicyBindingListerExpansion interface{}
// PolicyBindingNamespaceListerExpansion allows custom methods to be added to
// PolicyBindingNamespaceLister.
type PolicyBindingNamespaceListerExpansion interface{}
@@ -0,0 +1,70 @@
/*
Copyright The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
import (
policybindingv1alpha1 "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1"
labels "k8s.io/apimachinery/pkg/labels"
listers "k8s.io/client-go/listers"
cache "k8s.io/client-go/tools/cache"
)
// PolicyBindingLister helps list PolicyBindings.
// All objects returned here must be treated as read-only.
type PolicyBindingLister interface {
// List lists all PolicyBindings in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*policybindingv1alpha1.PolicyBinding, err error)
// PolicyBindings returns an object that can list and get PolicyBindings.
PolicyBindings(namespace string) PolicyBindingNamespaceLister
PolicyBindingListerExpansion
}
// policyBindingLister implements the PolicyBindingLister interface.
type policyBindingLister struct {
listers.ResourceIndexer[*policybindingv1alpha1.PolicyBinding]
}
// NewPolicyBindingLister returns a new PolicyBindingLister.
func NewPolicyBindingLister(indexer cache.Indexer) PolicyBindingLister {
return &policyBindingLister{listers.New[*policybindingv1alpha1.PolicyBinding](indexer, policybindingv1alpha1.Resource("policybinding"))}
}
// PolicyBindings returns an object that can list and get PolicyBindings.
func (s *policyBindingLister) PolicyBindings(namespace string) PolicyBindingNamespaceLister {
return policyBindingNamespaceLister{listers.NewNamespaced[*policybindingv1alpha1.PolicyBinding](s.ResourceIndexer, namespace)}
}
// PolicyBindingNamespaceLister helps list and get PolicyBindings.
// All objects returned here must be treated as read-only.
type PolicyBindingNamespaceLister interface {
// List lists all PolicyBindings in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*policybindingv1alpha1.PolicyBinding, err error)
// Get retrieves the PolicyBinding from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*policybindingv1alpha1.PolicyBinding, error)
PolicyBindingNamespaceListerExpansion
}
// policyBindingNamespaceLister implements the PolicyBindingNamespaceLister
// interface.
type policyBindingNamespaceLister struct {
listers.ResourceIndexer[*policybindingv1alpha1.PolicyBinding]
}
+324 -3
View File
@@ -32,6 +32,14 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.Application": schema_pkg_apis_application_v1alpha1_Application(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationList": schema_pkg_apis_application_v1alpha1_ApplicationList(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationSpec": schema_pkg_apis_application_v1alpha1_ApplicationSpec(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationStatus": schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBinding": schema_pkg_apis_policybinding_v1alpha1_PolicyBinding(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingList": schema_pkg_apis_policybinding_v1alpha1_PolicyBindingList(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingSpec": schema_pkg_apis_policybinding_v1alpha1_PolicyBindingSpec(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingStatus": schema_pkg_apis_policybinding_v1alpha1_PolicyBindingStatus(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1.ProxyProvider": schema_pkg_apis_proxyprovider_v1alpha1_ProxyProvider(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1.ProxyProviderList": schema_pkg_apis_proxyprovider_v1alpha1_ProxyProviderList(ref),
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/proxyprovider/v1alpha1.ProxyProviderSpec": schema_pkg_apis_proxyprovider_v1alpha1_ProxyProviderSpec(ref),
@@ -94,6 +102,312 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
}
}
func schema_pkg_apis_application_v1alpha1_Application(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(v1.ObjectMeta{}.OpenAPIModelName()),
},
},
"spec": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationStatus"),
},
},
},
Required: []string{"spec", "status"},
},
},
Dependencies: []string{
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationSpec", "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.ApplicationStatus", v1.ObjectMeta{}.OpenAPIModelName()},
}
}
func schema_pkg_apis_application_v1alpha1_ApplicationList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(v1.ListMeta{}.OpenAPIModelName()),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.Application"),
},
},
},
},
},
},
Required: []string{"items"},
},
},
Dependencies: []string{
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/application/v1alpha1.Application", v1.ListMeta{}.OpenAPIModelName()},
}
}
func schema_pkg_apis_application_v1alpha1_ApplicationSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"name": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"slug": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"provider": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
Format: "int32",
},
},
},
Required: []string{"name", "slug"},
},
},
}
}
func schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"pk": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"pk"},
},
},
}
}
func schema_pkg_apis_policybinding_v1alpha1_PolicyBinding(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(v1.ObjectMeta{}.OpenAPIModelName()),
},
},
"spec": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingSpec"),
},
},
"status": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingStatus"),
},
},
},
Required: []string{"spec", "status"},
},
},
Dependencies: []string{
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingSpec", "gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBindingStatus", v1.ObjectMeta{}.OpenAPIModelName()},
}
}
func schema_pkg_apis_policybinding_v1alpha1_PolicyBindingList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
"metadata": {
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref(v1.ListMeta{}.OpenAPIModelName()),
},
},
"items": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: ref("gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBinding"),
},
},
},
},
},
},
Required: []string{"items"},
},
},
Dependencies: []string{
"gitea.t000-n.de/t.behrendt/authentik-kubernetes-operator/pkg/apis/policybinding/v1alpha1.PolicyBinding", v1.ListMeta{}.OpenAPIModelName()},
}
}
func schema_pkg_apis_policybinding_v1alpha1_PolicyBindingSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"policy": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"group": {
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
"user": {
SchemaProps: spec.SchemaProps{
Type: []string{"integer"},
Format: "int32",
},
},
"target": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
"order": {
SchemaProps: spec.SchemaProps{
Default: 0,
Type: []string{"integer"},
Format: "int32",
},
},
},
Required: []string{"target", "order"},
},
},
}
}
func schema_pkg_apis_policybinding_v1alpha1_PolicyBindingStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"pk": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
},
},
Required: []string{"pk"},
},
},
}
}
func schema_pkg_apis_proxyprovider_v1alpha1_ProxyProvider(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -222,8 +536,15 @@ func schema_pkg_apis_proxyprovider_v1alpha1_ProxyProviderSpec(ref common.Referen
Format: "",
},
},
"outpost": {
SchemaProps: spec.SchemaProps{
Default: "",
Type: []string{"string"},
Format: "",
},
Required: []string{"name", "authorization_flow", "invalidation_flow", "external_host"},
},
},
Required: []string{"name", "authorization_flow", "invalidation_flow", "external_host", "outpost"},
},
},
}
@@ -2742,7 +3063,7 @@ func schema_k8sio_apimachinery_pkg_runtime_RawExtension(ref common.ReferenceCall
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned struct, and Object in your internal struct. You also need to register your various plugin types.\n\n// Internal package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\"\"`\n\t\tMyPlugin runtime.Object `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// External package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\"\"`\n\t\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// On the wire, the JSON will look something like this:\n\n\t{\n\t\t\"kind\":\"MyAPIObject\",\n\t\t\"apiVersion\":\"v1\",\n\t\t\"myPlugin\": {\n\t\t\t\"kind\":\"PluginA\",\n\t\t\t\"aOption\":\"foo\",\n\t\t},\n\t}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the Object. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)",
Description: "RawExtension is used to hold extensions in external versions.\n\nTo use this, make a field which has RawExtension as its type in your external, versioned struct, and Object in your internal struct. You also need to register your various plugin types.\n\n// Internal package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.Object `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// External package:\n\n\ttype MyAPIObject struct {\n\t\truntime.TypeMeta `json:\",inline\"`\n\t\tMyPlugin runtime.RawExtension `json:\"myPlugin\"`\n\t}\n\n\ttype PluginA struct {\n\t\tAOption string `json:\"aOption\"`\n\t}\n\n// On the wire, the JSON will look something like this:\n\n\t{\n\t\t\"kind\":\"MyAPIObject\",\n\t\t\"apiVersion\":\"v1\",\n\t\t\"myPlugin\": {\n\t\t\t\"kind\":\"PluginA\",\n\t\t\t\"aOption\":\"foo\",\n\t\t},\n\t}\n\nSo what happens? Decode first uses json or yaml to unmarshal the serialized data into your external MyAPIObject. That causes the raw JSON to be stored, but not unpacked. The next step is to copy (using pkg/conversion) into the internal struct. The runtime package's DefaultScheme has conversion functions installed which will unpack the JSON stored in RawExtension, turning it into the correct object type, and storing it in the Object. (TODO: In the case where the object is of an unknown type, a runtime.Unknown object will be created and stored.)",
Type: []string{"object"},
},
},
@@ -2753,7 +3074,7 @@ func schema_k8sio_apimachinery_pkg_runtime_TypeMeta(ref common.ReferenceCallback
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type, like this:\n\n\ttype MyAwesomeAPIObject struct {\n\t runtime.TypeMeta `json:\"\"`\n\t ... // other fields\n\t}\n\nfunc (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind\n\nTypeMeta is provided here for convenience. You may use it directly from this package or define your own with the same fields.",
Description: "TypeMeta is shared by all top level objects. The proper way to use it is to inline it in your type, like this:\n\n\ttype MyAwesomeAPIObject struct {\n\t runtime.TypeMeta `json:\",inline\"`\n\t ... // other fields\n\t}\n\nfunc (obj *MyAwesomeAPIObject) SetGroupVersionKind(gvk *metav1.GroupVersionKind) { metav1.UpdateTypeMeta(obj,gvk) }; GroupVersionKind() *GroupVersionKind\n\nTypeMeta is provided here for convenience. You may use it directly from this package or define your own with the same fields.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"apiVersion": {