Compare commits

...

153 Commits

Author SHA1 Message Date
768c61020e Merge pull request 'feature/add-namespace-to-firewallgroup-and-firewallpolicy-resources' (#29) from feature/add-namespace-to-firewallgroup-and-firewallpolicy-resources into main
All checks were successful
Publish / build (push) Successful in 1m58s
Reviewed-on: #29
2025-06-27 15:48:14 +00:00
8d70a78a50 fix
All checks were successful
Build project / build (push) Successful in 1m47s
Publish / build (push) Successful in 1m59s
2025-06-27 17:01:55 +02:00
5885daac55 Fix
Some checks failed
Build project / build (push) Failing after 1m9s
Publish / build (push) Failing after 1m19s
2025-06-27 16:53:44 +02:00
440dc04e5b Add namespace to some names
Some checks failed
Build project / build (push) Failing after 1m10s
Publish / build (push) Failing after 1m21s
2025-06-27 16:51:05 +02:00
22c8df6833 Add namespace to name of firewallgroups 2025-06-27 16:46:45 +02:00
35d95d107c Merge pull request 'Use pre-built image' (#28) from feature/use-prebuilt-image into main
Some checks failed
Publish / build (push) Has been cancelled
Reviewed-on: #28
2025-06-26 23:49:34 +00:00
4bb45b0128 Use pre-built image
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Successful in 1m54s
2025-06-27 01:47:15 +02:00
9eefd08823 Merge pull request 'Add variables' (#27) from feature/fix-indentation into main
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Has been cancelled
Reviewed-on: #27
2025-06-26 23:36:27 +00:00
d53810b714 Add variables
Some checks failed
Build project / build (push) Has been cancelled
2025-06-27 01:36:01 +02:00
33f1fd5eac Merge pull request 'Need docker on main build' (#26) from feature/fix-indentation into main
Some checks failed
Publish / build (push) Failing after 2m21s
Reviewed-on: #26
2025-06-26 23:28:36 +00:00
9ae7d91365 Need docker on main build
Some checks failed
Build project / build (push) Has been cancelled
2025-06-27 01:28:01 +02:00
6fe5fdf859 Merge pull request 'Fix indentation' (#25) from feature/fix-indentation into main
Some checks failed
Publish / build (push) Failing after 1m9s
Reviewed-on: #25
2025-06-26 23:24:16 +00:00
37b5eb830a Fix indentation
Some checks failed
Build project / build (push) Has been cancelled
2025-06-27 01:23:49 +02:00
1834527d43 feature/create-correct-manifests (#23)
Reviewed-on: #23
2025-06-26 23:19:55 +00:00
b562c200ba Merge pull request 'split up regex' (#22) from feature/build-alpha-and-beta into main
All checks were successful
Publish / build (push) Successful in 2m53s
Reviewed-on: #22
2025-06-26 22:19:58 +00:00
2485365728 split up regex
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Successful in 3m22s
2025-06-27 00:18:05 +02:00
efeaf521fd Merge pull request 'match alpha and beta tags' (#21) from feature/build-alpha-and-beta into main
All checks were successful
Publish / build (push) Successful in 2m55s
Reviewed-on: #21
2025-06-26 22:08:57 +00:00
7ce8682ecb match alpha and beta tags
All checks were successful
Build project / build (push) Successful in 2m14s
2025-06-27 00:07:04 +02:00
744e43c1f4 Merge pull request 'Add image url' (#20) from feature/update-image-labels into main
All checks were successful
Publish / build (push) Successful in 3m22s
Reviewed-on: #20
2025-06-26 19:35:12 +00:00
8095723337 Add image url
Some checks failed
Build project / build (push) Has been cancelled
2025-06-26 21:34:42 +02:00
9e7b6123c2 Merge pull request 'Override image labels' (#19) from feature/update-image-labels into main
All checks were successful
Publish / build (push) Successful in 3m15s
Reviewed-on: #19
2025-06-26 19:14:46 +00:00
062b386f7f Override image labels
All checks were successful
Build project / build (push) Successful in 1m54s
2025-06-26 21:14:23 +02:00
aca35507ba Merge pull request 'Override image labels' (#18) from feature/update-image-labels into main
Some checks failed
Publish / build (push) Failing after 1m35s
Reviewed-on: #18
2025-06-26 19:06:58 +00:00
4ede272b70 Override image labels
All checks were successful
Build project / build (push) Successful in 1m58s
2025-06-26 21:06:25 +02:00
5e413a64e8 Merge pull request 'Add ko.yaml' (#17) from feature/update-image-labels into main
All checks were successful
Publish / build (push) Successful in 3m22s
Reviewed-on: #17
2025-06-26 18:22:11 +00:00
1cfd5ef55c Add ko.yaml
All checks were successful
Build project / build (push) Successful in 2m1s
2025-06-26 20:21:45 +02:00
c89dad396b Merge pull request 'feature/generate-manifest' (#16) from feature/generate-manifest into main
All checks were successful
Publish / build (push) Successful in 3m17s
Reviewed-on: #16
2025-06-25 18:30:29 +00:00
cddda7098c generic in the path
All checks were successful
Build project / build (push) Successful in 1m59s
2025-06-25 20:29:15 +02:00
9a186ad190 Add forgotten files
All checks were successful
Build project / build (push) Successful in 1m58s
2025-06-25 17:52:28 +02:00
4ece12d18b Merge pull request 'Upload manifest' (#15) from feature/generate-manifest into main
All checks were successful
Publish / build (push) Successful in 3m15s
Reviewed-on: #15
2025-06-25 15:48:20 +00:00
6d0df79c87 Upload manifest
All checks were successful
Build project / build (push) Successful in 1m27s
2025-06-25 17:45:02 +02:00
445dd7830e Merge pull request 'Use image from gitea' (#14) from feature/use-image-from-gitea into main
All checks were successful
Publish / build (push) Successful in 2m19s
Reviewed-on: #14
2025-06-25 15:26:34 +00:00
a73aef4f9d Use image from gitea
All checks were successful
Build project / build (push) Successful in 1m29s
2025-06-25 17:25:05 +02:00
a99de02594 Merge pull request 'Fix variable reference' (#13) from feature/fix-variable into main
All checks were successful
Publish / build (push) Successful in 3m2s
Reviewed-on: #13
2025-06-25 15:09:34 +00:00
893318ad53 Fix variable reference
Some checks failed
Build project / build (push) Has been cancelled
2025-06-25 17:09:15 +02:00
201edb1b82 Merge pull request 'feature/fix' (#12) from feature/fix into main
Some checks failed
Publish / build (push) Failing after 1m34s
Reviewed-on: #12
2025-06-25 15:01:09 +00:00
b1c0a4ee11 :q:Merge branch 'feature/fix-push-workflow'
All checks were successful
Build project / build (push) Successful in 1m28s
2025-06-25 16:59:39 +02:00
13677136a7 Fix variable reference
Some checks failed
Build project / build (push) Has been cancelled
2025-06-25 16:57:02 +02:00
cb296c3881 Fix variable reference 2025-06-25 16:57:02 +02:00
3c6b48803d fix secret names 2025-06-25 16:57:02 +02:00
f71fa2af8e Add missing sign 2025-06-25 16:57:02 +02:00
1819ef2b60 Fix workflow 2025-06-25 16:57:02 +02:00
74d7ca84a5 Change package repo 2025-06-25 16:57:02 +02:00
0f7ffe3c85 cleanup 2025-06-25 16:57:02 +02:00
3020510c6f bare 2025-06-25 16:57:01 +02:00
475e226b69 fix 2025-06-25 16:57:01 +02:00
a5521013b9 fix 2025-06-25 16:57:01 +02:00
4aa3436f28 fix 2025-06-25 16:57:01 +02:00
6e32555e9e fix 2025-06-25 16:57:01 +02:00
13c23863be fix 2025-06-25 16:57:01 +02:00
918b45c940 fix 2025-06-25 16:57:01 +02:00
3cb65a5a14 fix 2025-06-25 16:57:00 +02:00
4ae70ecf74 fix 2025-06-25 16:57:00 +02:00
3aa4d1a24a fix 2025-06-25 16:57:00 +02:00
1231bc50e5 fix 2025-06-25 16:57:00 +02:00
e1847f4cf9 fix 2025-06-25 16:57:00 +02:00
55a206d509 fix 2025-06-25 16:57:00 +02:00
00179595e4 fix 2025-06-25 16:57:00 +02:00
f09e008fb7 fix 2025-06-25 16:57:00 +02:00
14a8155dcf fix 2025-06-25 16:57:00 +02:00
93ef66f01d fix 2025-06-25 16:57:00 +02:00
80746321a9 fix 2025-06-25 16:57:00 +02:00
6423ef7d6e fix 2025-06-25 16:57:00 +02:00
fdefd05608 fix 2025-06-25 16:57:00 +02:00
760fd3903f fix 2025-06-25 16:57:00 +02:00
cda1c7ddff fix 2025-06-25 16:57:00 +02:00
1274fe610f fix 2025-06-25 16:57:00 +02:00
f091ec148b Tag 2025-06-25 16:57:00 +02:00
66e1d854d3 Tag 2025-06-25 16:57:00 +02:00
f43c1f3b63 fix tagging 2025-06-25 16:57:00 +02:00
0046157633 Fix variable reference (#10)
Some checks failed
Publish / build (push) Failing after 1m33s
Reviewed-on: #10
Co-authored-by: Vegard Engen <vegard@engen.priv.no>
Co-committed-by: Vegard Engen <vegard@engen.priv.no>
2025-06-25 14:52:55 +00:00
56a781a260 Merge pull request 'fix secret names' (#9) from feature/fix-push-workflow into main
Some checks failed
Publish / build (push) Failing after 1m34s
Reviewed-on: #9
2025-06-25 14:35:35 +00:00
29fb9601fd fix secret names
Some checks failed
Build project / build (push) Has been cancelled
2025-06-25 16:35:12 +02:00
c34eea5e13 Merge pull request 'Add missing sign' (#8) from feature/fix-push-workflow into main
Some checks failed
Publish / build (push) Failing after 1m34s
Reviewed-on: #8
2025-06-25 14:30:15 +00:00
fe90ac7ea4 Add missing sign
Some checks failed
Build project / build (push) Has been cancelled
2025-06-25 16:29:37 +02:00
31679a3f53 Merge pull request 'Fix workflow' (#7) from feature/fix-push-workflow into main
Some checks failed
Publish / build (push) Has been cancelled
Reviewed-on: #7
2025-06-25 14:25:22 +00:00
de38c76e24 Fix workflow
Some checks failed
Build project / build (push) Has been cancelled
2025-06-25 16:25:03 +02:00
2a396ad981 Merge pull request 'Change package repo' (#6) from feature/push-to-gitea into main
All checks were successful
Publish / build (push) Successful in 2m20s
Reviewed-on: #6
2025-06-25 14:21:03 +00:00
f147ec8108 Change package repo
Some checks failed
Build project / build (push) Has been cancelled
2025-06-25 16:20:35 +02:00
b6a2b73eb8 Merge pull request 'cleanup' (#5) from feature/clean_some_files into main
All checks were successful
Publish / build (push) Successful in 2m20s
Reviewed-on: #5
2025-06-25 13:41:23 +00:00
2304e33586 cleanup
All checks were successful
Build project / build (push) Successful in 1m33s
2025-06-25 15:40:02 +02:00
a40f1342fe Merge pull request 'feature/fix-publish-pipeline' (#4) from feature/fix-publish-pipeline into main
All checks were successful
Publish / build (push) Successful in 2m29s
Reviewed-on: #4
2025-06-24 21:13:12 +00:00
bd8d1f7c01 bare
All checks were successful
Build project / build (push) Successful in 1m48s
Publish / build (push) Successful in 2m26s
2025-06-24 23:12:39 +02:00
ac47c880ed fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Successful in 2m21s
2025-06-24 12:01:15 +02:00
481091160b fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m6s
2025-06-24 11:58:06 +02:00
14e4fe1c46 fix
Some checks failed
Publish / build (push) Has been cancelled
Build project / build (push) Has been cancelled
2025-06-24 11:57:31 +02:00
4901dfbad5 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m8s
2025-06-24 11:56:05 +02:00
c454c78478 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m5s
2025-06-24 11:53:10 +02:00
c30e27efc4 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m6s
2025-06-24 11:43:37 +02:00
f2a943de3c fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 11:41:12 +02:00
720865c984 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 11:39:41 +02:00
913a24a613 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m6s
2025-06-24 11:33:40 +02:00
719ba853bc fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m8s
2025-06-24 11:31:09 +02:00
4e26fe02f5 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 3s
2025-06-24 11:29:54 +02:00
cd61d5c82a fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 0s
2025-06-24 11:29:25 +02:00
6983253c9e fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 3s
2025-06-24 11:26:23 +02:00
1d7c7c864e fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1s
2025-06-24 11:25:03 +02:00
1a2def25bf fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1s
2025-06-24 11:21:51 +02:00
6c8503bf15 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m8s
2025-06-24 11:17:03 +02:00
b9b86e0d5d fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 2m14s
2025-06-24 11:10:19 +02:00
2c9659409c fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 2m46s
2025-06-24 11:05:01 +02:00
20c4dda5ad fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 11:02:18 +02:00
bb28850ca5 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 34s
2025-06-24 10:58:27 +02:00
f08c165628 fix
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m13s
2025-06-24 10:54:43 +02:00
46e6217557 fix
Some checks failed
Build project / build (push) Successful in 1m29s
Publish / build (push) Failing after 1s
2025-06-24 10:52:17 +02:00
36f337434d Tag
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 10:47:51 +02:00
3f14d82679 Tag
Some checks failed
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m11s
2025-06-24 10:42:24 +02:00
2817272082 Merge pull request 'fix tagging' (#3) from feature/fix-publish-pipeline into main
Some checks failed
Publish / build (push) Failing after 1m7s
Reviewed-on: #3
2025-06-24 08:35:30 +00:00
1545f05d53 fix tagging
Some checks failed
Build project / build (push) Has been cancelled
2025-06-24 10:35:05 +02:00
47116c70b5 Merge pull request 'ko build --local on main' (#2) from feature/kobuild-on-main into main
All checks were successful
Publish / build (push) Successful in 2m24s
Reviewed-on: #2
2025-06-24 08:24:32 +00:00
0eb5b5c2eb ko build --local on main
All checks were successful
Build project / build (push) Successful in 1m27s
2025-06-24 10:23:55 +02:00
7e6573deb4 Merge pull request 'ko build on main' (#1) from feature/kobuild-on-main into main
All checks were successful
Publish / build (push) Successful in 2m19s
Reviewed-on: #1
2025-06-24 08:15:36 +00:00
e22a4c4992 ko build on main
All checks were successful
Build project / build (push) Successful in 1m27s
2025-06-24 10:14:52 +02:00
401f4a7cf7 build on non-main
All checks were successful
Build project / build (push) Successful in 1m30s
2025-06-24 10:10:56 +02:00
68e8782da4 Publish
All checks were successful
Publish / build (push) Successful in 2m20s
2025-06-24 10:03:25 +02:00
e95a4c13e6 Publish
Some checks failed
Publish / build (push) Failing after 1m7s
2025-06-24 10:00:49 +02:00
d82d7d2902 Build only on branch push 2025-06-24 09:59:45 +02:00
3091c89fa8 Build only on branch push 2025-06-24 09:57:32 +02:00
853fca1635 Build only on branch push 2025-06-24 09:57:01 +02:00
07208979e3 Build only on branch push 2025-06-24 09:56:05 +02:00
c86196aa88 ko
Some checks failed
Build project / build (push) Successful in 1m26s
Publish / build (push) Failing after 1m9s
2025-06-24 09:48:43 +02:00
a35bc7220d pipelines
All checks were successful
Build project / build (push) Successful in 1m29s
2025-06-24 09:44:19 +02:00
446fb89d00 Change workflow 2025-06-24 09:40:44 +02:00
4bf3adaf87 test
All checks were successful
Build & Push Linode Webhook / build (push) Successful in 1m30s
2025-06-24 01:48:34 +02:00
d7f2d8031e fix
All checks were successful
Build & Push Linode Webhook / build (push) Successful in 1m31s
2025-06-24 01:47:34 +02:00
604cc20505 fix
All checks were successful
Build & Push Linode Webhook / build (push) Successful in 1m32s
2025-06-24 01:45:10 +02:00
572521747f fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 7s
2025-06-24 01:43:34 +02:00
acea7fd46e fix 2025-06-24 01:42:50 +02:00
634021854d fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 33s
2025-06-24 01:34:02 +02:00
1e0a51f83b fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 6s
2025-06-24 01:33:19 +02:00
cab7bc2f5a fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 2s
2025-06-24 01:31:49 +02:00
cef43b9c3e fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 25s
2025-06-24 01:29:31 +02:00
019a33a69a fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 2s
2025-06-24 01:27:30 +02:00
c2ff504510 fix
Some checks failed
Build & Push Linode Webhook / build (push) Failing after 3s
2025-06-24 01:26:43 +02:00
55ef068855 fix 2025-06-24 01:26:08 +02:00
babbf2ed97 Workflow 2025-06-24 00:14:08 +02:00
8765a94893 Rename
Some checks failed
Lint / Run on Ubuntu (push) Failing after 7s
E2E Tests / Run on Ubuntu (push) Failing after 3s
Tests / Run on Ubuntu (push) Failing after 3s
2025-06-24 00:12:16 +02:00
54ade7cc49 rename
Some checks failed
Lint / Run on Ubuntu (push) Failing after 6s
E2E Tests / Run on Ubuntu (push) Failing after 2s
Tests / Run on Ubuntu (push) Failing after 3s
2025-06-24 00:07:51 +02:00
bf666f0a89 rename
Some checks failed
Lint / Run on Ubuntu (push) Failing after 7s
E2E Tests / Run on Ubuntu (push) Failing after 3s
Tests / Run on Ubuntu (push) Failing after 3s
2025-06-24 00:06:39 +02:00
b59fc563f3 rename
Some checks failed
Lint / Run on Ubuntu (push) Failing after 6s
E2E Tests / Run on Ubuntu (push) Failing after 3s
Tests / Run on Ubuntu (push) Failing after 4s
2025-06-23 23:50:53 +02:00
b444690400 Merge pull request #40 from vegardengen/39-port-forwards-should-not-log-per-default
Turn off logging for newly created portforward rules
2025-06-11 10:14:56 +02:00
bcf73d64bf Turn off logging for newly created portforward rules 2025-06-11 10:13:48 +02:00
d372e4c7a7 Merge pull request #38 from vegardengen/37-optimize-api-usage
37 optimize api usage
2025-06-04 22:12:51 +02:00
c80473d9e8 workaround for bug? 2025-06-04 22:02:48 +02:00
bcffdfede7 Change leader election 2025-06-04 20:56:52 +02:00
d7a444c8d7 Change an ID in Delete firewallgroup 2025-06-04 20:56:37 +02:00
df9926e3da Small fix on updating firewall group/deleting component of it in Unifi 2025-06-04 19:10:03 +02:00
c2ffce2d4d Do a few less updates 2025-06-04 18:29:26 +02:00
fc0bda1e7b Merge pull request #36 from vegardengen/35-fix-portforward-logic
Check if portfoward already exists, and update if needed
2025-04-22 07:34:48 +02:00
dd4df6ee07 Check if portfoward already exists, and update if needed 2025-04-22 07:33:05 +02:00
86b58cb5a9 Merge pull request #34 from vegardengen/11-create-port-forward-api
Portforward API
2025-04-21 10:37:11 +02:00
6aed3728cc Portforward API 2025-04-21 10:35:39 +02:00
3167397a81 Merge pull request #33 from vegardengen/32-refactor-unifi-firewall-rule-api
32 refactor unifi firewall rule api
2025-04-21 01:42:56 +02:00
34 changed files with 1709 additions and 1884 deletions

View File

@@ -0,0 +1,26 @@
name: Build project
on:
push:
branches-ignore:
- main
jobs:
build:
runs-on: ubuntu-latest
container: registry.engen.priv.no/gitea-build:0.1.0
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan gitea-ssh.engen.priv.no >> ~/.ssh/known_hosts
- name: Install node and go
run: apt update && apt -y install nodejs
- name: Check out repository code
uses: actions/checkout@v4
- name: ssh repo
run: git config --global url.git@gitea-ssh.engen.priv.no:.insteadOf https://gitea.engen.priv.no/
- name: Build
run: go build cmd/main.go
- name: Build manifest
run: make build-installer

View File

@@ -0,0 +1,50 @@
name: Publish
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
container: registry.engen.priv.no/gitea-build:0.1.0
env:
GITEA_USER: ${{ secrets.GITEAUSER }}
GITEA_TOKEN: ${{ secrets.GITEATOKEN }}
GITEA_REGISTRY: gitea.engen.priv.no
GITEA_ORG: klauvsteinen
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan gitea-ssh.engen.priv.no >> ~/.ssh/known_hosts
- name: Check out repository code
uses: actions/checkout@v4
- name: ssh repo
run: git config --global url.git@gitea-ssh.engen.priv.no:.insteadOf https://gitea.engen.priv.no/
- name: Docker login
run: echo "${GITEA_TOKEN}" | docker login "${GITEA_REGISTRY}" --username "${GITEA_USER}" --password-stdin
- name: Build
run: |
export KO_DOCKER_REPO="${GITEA_REGISTRY}/${GITEA_ORG}/unifi-network-operator-controller"
ko publish ./cmd \
--tags "latest" \
--image-label 'org.opencontainers.image.authors=Klauvsteinen <vegard@engen.priv.no>' \
--image-label 'org.opencontainers.image.vendor=Klauvsteinen' \
--image-label 'org.opencontainers.image.source=https://gitea.engen.priv.no/klauvsteinen/unifi-network-operator' \
--image-label 'org.opencontainers.image.url=https://gitea.engen.priv.no/klauvsteinen/unifi-network-operator' \
--image-label 'dev.chainguard.package.main=' \
--bare
- name: Build manifest
run: |
make IMG="${GITEA_REGISTRY}/${GITEA_ORG}/unifi-network-operator-controller:latest" build-installer
curl -X DELETE \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/x-yaml" \
https://gitea.engen.priv.no/api/packages/klauvsteinen/generic/unifi-network-operator/latest/install.yaml
curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/x-yaml" \
--data-binary @./dist/install.yaml \
https://gitea.engen.priv.no/api/packages/klauvsteinen/generic/unifi-network-operator/latest/install.yaml

View File

@@ -0,0 +1,54 @@
name: Publish
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-alpha[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-beta[0-9]+'
jobs:
build:
runs-on: ubuntu-latest
container: registry.engen.priv.no/gitea-build:0.1.0
env:
GITEA_USER: ${{ secrets.GITEAUSER }}
GITEA_TOKEN: ${{ secrets.GITEATOKEN }}
GITEA_REGISTRY: gitea.engen.priv.no
GITEA_ORG: klauvsteinen
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan gitea-ssh.engen.priv.no >> ~/.ssh/known_hosts
- name: Check out repository code
uses: actions/checkout@v4
- name: ssh repo
run: git config --global url.git@gitea-ssh.engen.priv.no:.insteadOf https://gitea.engen.priv.no/
- name: Extract tag (outside container)
shell: bash
run: |
echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
env
- name: Docker login
run: echo "${GITEA_TOKEN}" | docker login "${GITEA_REGISTRY}" --username "${GITEA_USER}" --password-stdin
- name: Build
run: |
export KO_DOCKER_REPO="${GITEA_REGISTRY}/${GITEA_ORG}/unifi-network-operator-controller"
ko publish ./cmd \
--tags "$TAG" \
--image-label 'org.opencontainers.image.authors=Klauvsteinen <vegard@engen.priv.no>' \
--image-label 'org.opencontainers.image.vendor=Klauvsteinen' \
--image-label 'org.opencontainers.image.source=https://gitea.engen.priv.no/klauvsteinen/unifi-network-operator' \
--image-label 'org.opencontainers.image.url=https://gitea.engen.priv.no/klauvsteinen/unifi-network-operator' \
--image-label 'dev.chainguard.package.main=' \
--bare
- name: Build manifest
run: |
make IMG="${GITEA_REGISTRY}/${GITEA_ORG}/unifi-network-operator-controller:$TAG" build-installer
curl -X PUT \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/x-yaml" \
--data-binary @./dist/install.yaml \
https://gitea.engen.priv.no/api/packages/klauvsteinen/generic/unifi-network-operator/$TAG/install.yaml

View File

@@ -1,5 +1,5 @@
# Image URL to use all building/pushing image targets # Image URL to use all building/pushing image targets
IMG ?= registry.engen.priv.no/unifi-network-operator-controller:latest IMG ?= gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller:latest
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN)) ifeq (,$(shell go env GOBIN))
@@ -8,7 +8,7 @@ else
GOBIN=$(shell go env GOBIN) GOBIN=$(shell go env GOBIN)
endif endif
export KO_DOCKER_REPO=registry.engen.priv.no/unifi-network-operator-controller export KO_DOCKER_REPO=gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller
# CONTAINER_TOOL defines the container tool to be used for building images. # CONTAINER_TOOL defines the container tool to be used for building images.
# Be aware that the target commands are only tested with Docker which is # Be aware that the target commands are only tested with Docker which is

17
PROJECT
View File

@@ -6,7 +6,7 @@ domain: engen.priv.no
layout: layout:
- go.kubebuilder.io/v4 - go.kubebuilder.io/v4
projectName: unifi-network-operator projectName: unifi-network-operator
repo: github.com/vegardengen/unifi-network-operator repo: gitea.engen.priv.no/klauvsteinen/unifi-network-operator
resources: resources:
- api: - api:
crdVersion: v1 crdVersion: v1
@@ -15,7 +15,7 @@ resources:
domain: engen.priv.no domain: engen.priv.no
group: unifi group: unifi
kind: Networkconfiguration kind: Networkconfiguration
path: github.com/vegardengen/unifi-network-operator/api/v1beta1 path: gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1
version: v1beta1 version: v1beta1
- api: - api:
crdVersion: v1 crdVersion: v1
@@ -24,7 +24,7 @@ resources:
domain: engen.priv.no domain: engen.priv.no
group: unifi group: unifi
kind: FirewallZone kind: FirewallZone
path: github.com/vegardengen/unifi-network-operator/api/v1beta1 path: gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1
version: v1beta1 version: v1beta1
- api: - api:
crdVersion: v1 crdVersion: v1
@@ -33,6 +33,15 @@ resources:
domain: engen.priv.no domain: engen.priv.no
group: unifi group: unifi
kind: FirewallPolicy kind: FirewallPolicy
path: github.com/vegardengen/unifi-network-operator/api/v1beta1 path: gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: engen.priv.no
group: unifi
kind: PortForward
path: gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1
version: v1beta1 version: v1beta1
version: "3" version: "3"

View File

@@ -0,0 +1,48 @@
/*
Copyright 2025 Vegard Engen.
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 v1beta1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// PortForward is a placeholder type to allow future CRD support if needed.
// Right now, port forwards are managed entirely through annotations on Services.
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
type PortForward struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec PortForwardSpec `json:"spec,omitempty"`
Status PortForwardStatus `json:"status,omitempty"`
}
type PortForwardSpec struct {
// Reserved for future CRD-based management
}
type PortForwardStatus struct {
// Reserved for future CRD-based status
}
// PortForwardList contains a list of PortForward
// Currently unused, defined for completeness
type PortForwardList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []PortForward `json:"items"`
}

View File

@@ -682,6 +682,87 @@ func (in *NetworkconfigurationStatus) DeepCopy() *NetworkconfigurationStatus {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PortForward) DeepCopyInto(out *PortForward) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
out.Status = in.Status
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortForward.
func (in *PortForward) DeepCopy() *PortForward {
if in == nil {
return nil
}
out := new(PortForward)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PortForward) 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 *PortForwardList) DeepCopyInto(out *PortForwardList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PortForward, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortForwardList.
func (in *PortForwardList) DeepCopy() *PortForwardList {
if in == nil {
return nil
}
out := new(PortForwardList)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PortForwardSpec) DeepCopyInto(out *PortForwardSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortForwardSpec.
func (in *PortForwardSpec) DeepCopy() *PortForwardSpec {
if in == nil {
return nil
}
out := new(PortForwardSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PortForwardStatus) DeepCopyInto(out *PortForwardStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PortForwardStatus.
func (in *PortForwardStatus) DeepCopy() *PortForwardStatus {
if in == nil {
return nil
}
out := new(PortForwardStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ServiceEntry) DeepCopyInto(out *ServiceEntry) { func (in *ServiceEntry) DeepCopyInto(out *ServiceEntry) {
*out = *in *out = *in

View File

@@ -21,11 +21,13 @@ import (
"flag" "flag"
"os" "os"
"path/filepath" "path/filepath"
"time"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them. // to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/utils/pointer"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme" clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -37,10 +39,10 @@ import (
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/controller" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/controller"
"github.com/vegardengen/unifi-network-operator/internal/unifi" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
// +kubebuilder:scaffold:imports // +kubebuilder:scaffold:imports
) )
@@ -187,6 +189,10 @@ func main() {
HealthProbeBindAddress: probeAddr, HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection, LeaderElection: enableLeaderElection,
LeaderElectionID: "f05533b6.engen.priv.no", LeaderElectionID: "f05533b6.engen.priv.no",
LeaseDuration: pointer.Duration(30 * time.Second),
RenewDeadline: pointer.Duration(20 * time.Second),
RetryPeriod: pointer.Duration(5 * time.Second),
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily // LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
// when the Manager ends. This requires the binary to immediately end when the // when the Manager ends. This requires the binary to immediately end when the
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly // Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
@@ -242,6 +248,15 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "FirewallPolicy") setupLog.Error(err, "unable to create controller", "controller", "FirewallPolicy")
os.Exit(1) os.Exit(1)
} }
if err = (&controller.PortForwardReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
UnifiClient: unifiClient,
ConfigLoader: configLoader,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "PortForward")
os.Exit(1)
}
// +kubebuilder:scaffold:builder // +kubebuilder:scaffold:builder
if err = (&controller.FirewallGroupReconciler{ if err = (&controller.FirewallGroupReconciler{

View File

@@ -0,0 +1,49 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: portforwards.unifi.engen.priv.no
spec:
group: unifi.engen.priv.no
names:
kind: PortForward
listKind: PortForwardList
plural: portforwards
singular: portforward
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: |-
PortForward is a placeholder type to allow future CRD support if needed.
Right now, port forwards are managed entirely through annotations on Services.
properties:
apiVersion:
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
kind:
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
metadata:
type: object
spec:
type: object
status:
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -5,6 +5,7 @@ resources:
- bases/unifi.engen.priv.no_networkconfigurations.yaml - bases/unifi.engen.priv.no_networkconfigurations.yaml
- bases/unifi.engen.priv.no_firewallzones.yaml - bases/unifi.engen.priv.no_firewallzones.yaml
- bases/unifi.engen.priv.no_firewallpolicies.yaml - bases/unifi.engen.priv.no_firewallpolicies.yaml
- bases/unifi.engen.priv.no_portforwards.yaml
# +kubebuilder:scaffold:crdkustomizeresource # +kubebuilder:scaffold:crdkustomizeresource
patches: patches:

View File

@@ -4,5 +4,5 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
images: images:
- name: controller - name: controller
newName: registry.engen.priv.no/unifi-network-operator-controller newName: gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller
newTag: latest newTag: latest

View File

@@ -22,6 +22,9 @@ resources:
# default, aiding admins in cluster management. Those roles are # default, aiding admins in cluster management. Those roles are
# not used by the {{ .ProjectName }} itself. You can comment the following lines # not used by the {{ .ProjectName }} itself. You can comment the following lines
# if you do not want those helpers be installed with your Project. # if you do not want those helpers be installed with your Project.
- portforward_admin_role.yaml
- portforward_editor_role.yaml
- portforward_viewer_role.yaml
- firewallpolicy_admin_role.yaml - firewallpolicy_admin_role.yaml
- firewallpolicy_editor_role.yaml - firewallpolicy_editor_role.yaml
- firewallpolicy_viewer_role.yaml - firewallpolicy_viewer_role.yaml

View File

@@ -0,0 +1,27 @@
# This rule is not used by the project unifi-network-operator itself.
# It is provided to allow the cluster admin to help manage permissions for users.
#
# Grants full permissions ('*') over unifi.engen.priv.no.
# This role is intended for users authorized to modify roles and bindings within the cluster,
# enabling them to delegate specific permissions to other users or groups as needed.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: unifi-network-operator
app.kubernetes.io/managed-by: kustomize
name: portforward-admin-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards
verbs:
- '*'
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards/status
verbs:
- get

View File

@@ -0,0 +1,33 @@
# This rule is not used by the project unifi-network-operator itself.
# It is provided to allow the cluster admin to help manage permissions for users.
#
# Grants permissions to create, update, and delete resources within the unifi.engen.priv.no.
# This role is intended for users who need to manage these resources
# but should not control RBAC or manage permissions for others.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: unifi-network-operator
app.kubernetes.io/managed-by: kustomize
name: portforward-editor-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards/status
verbs:
- get

View File

@@ -0,0 +1,29 @@
# This rule is not used by the project unifi-network-operator itself.
# It is provided to allow the cluster admin to help manage permissions for users.
#
# Grants read-only access to unifi.engen.priv.no resources.
# This role is intended for users who need visibility into these resources
# without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: unifi-network-operator
app.kubernetes.io/managed-by: kustomize
name: portforward-viewer-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards
verbs:
- get
- list
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards/status
verbs:
- get

View File

@@ -20,6 +20,7 @@ rules:
- firewallpolicies - firewallpolicies
- firewallzones - firewallzones
- networkconfigurations - networkconfigurations
- portforwards
verbs: verbs:
- create - create
- delete - delete
@@ -35,6 +36,7 @@ rules:
- firewallpolicies/finalizers - firewallpolicies/finalizers
- firewallzones/finalizers - firewallzones/finalizers
- networkconfigurations/finalizers - networkconfigurations/finalizers
- portforwards/finalizers
verbs: verbs:
- update - update
- apiGroups: - apiGroups:
@@ -44,6 +46,7 @@ rules:
- firewallpolicies/status - firewallpolicies/status
- firewallzones/status - firewallzones/status
- networkconfigurations/status - networkconfigurations/status
- portforwards/status
verbs: verbs:
- get - get
- patch - patch

View File

@@ -3,4 +3,5 @@ resources:
- unifi_v1beta1_networkconfiguration.yaml - unifi_v1beta1_networkconfiguration.yaml
- unifi_v1beta1_firewallzone.yaml - unifi_v1beta1_firewallzone.yaml
- unifi_v1beta1_firewallrule.yaml - unifi_v1beta1_firewallrule.yaml
- unifi_v1beta1_portforward.yaml
# +kubebuilder:scaffold:manifestskustomizesamples # +kubebuilder:scaffold:manifestskustomizesamples

View File

@@ -0,0 +1,9 @@
apiVersion: unifi.engen.priv.no/v1beta1
kind: PortForward
metadata:
labels:
app.kubernetes.io/name: unifi-network-operator
app.kubernetes.io/managed-by: kustomize
name: portforward-sample
spec:
# TODO(user): Add fields here

952
dist/install.yaml vendored Normal file
View File

@@ -0,0 +1,952 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
control-plane: controller-manager
name: unifi-network-operator-system
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: firewallpolicies.unifi.engen.priv.no
spec:
group: unifi.engen.priv.no
names:
kind: FirewallPolicy
listKind: FirewallPolicyList
plural: firewallpolicies
singular: firewallpolicy
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: FirewallPolicy is the Schema for the firewallpolicies API.
properties:
apiVersion:
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
kind:
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
metadata:
type: object
spec:
properties:
destination:
properties:
firewall_groups:
items:
properties:
name:
type: string
namespace:
type: string
type: object
type: array
services:
items:
properties:
name:
type: string
namespace:
type: string
type: object
type: array
type: object
match_firewall_groups_in_all_namespaces:
type: boolean
match_services_in_all_namespaces:
type: boolean
name:
type: string
source:
properties:
from_networks:
items:
properties:
name:
type: string
namespace:
type: string
type: object
type: array
from_zones:
items:
properties:
name:
type: string
namespace:
type: string
type: object
type: array
type: object
required:
- destination
- name
- source
type: object
status:
description: FirewallPolicyStatus defines the observed state of FirewallPolicy.
properties:
resources_managed:
properties:
firewall_groups_managed:
items:
properties:
name:
type: string
namespace:
type: string
type: object
type: array
firewall_policies_managed:
items:
properties:
from:
type: string
tcpipv4_id:
type: string
tcpipv6_id:
type: string
to:
type: string
udpipv4_id:
type: string
udpipv6_id:
type: string
required:
- from
- tcpipv4_id
- tcpipv6_id
- to
- udpipv4_id
- udpipv6_id
type: object
type: array
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: firewallzones.unifi.engen.priv.no
spec:
group: unifi.engen.priv.no
names:
kind: FirewallZone
listKind: FirewallZoneList
plural: firewallzones
singular: firewallzone
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: FirewallZone is the Schema for the firewallzones API.
properties:
apiVersion:
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
kind:
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
metadata:
type: object
spec:
description: FirewallZoneSpec defines the desired state of FirewallZone.
properties:
_id:
type: string
default_zone:
type: boolean
name:
type: string
network_ids:
items:
type: string
type: array
zone_key:
type: string
type: object
status:
description: FirewallZoneStatus defines the observed state of FirewallZone.
properties:
resources_managed:
properties:
firewall_zones_managed:
items:
properties:
id:
type: string
name:
type: string
type: object
type: array
type: object
type: object
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: networkconfigurations.unifi.engen.priv.no
spec:
group: unifi.engen.priv.no
names:
kind: Networkconfiguration
listKind: NetworkconfigurationList
plural: networkconfigurations
singular: networkconfiguration
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: Networkconfiguration is the Schema for the networkconfigurations
API.
properties:
apiVersion:
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
kind:
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
metadata:
type: object
spec:
description: NetworkconfigurationSpec defines the desired state of Networkconfiguration.
properties:
_id:
description: Foo is an example field of Networkconfiguration. Edit
networkconfiguration_types.go to remove/update
type: string
enabled:
type: boolean
firewall_zone:
type: string
gateway_type:
type: string
ip_subnet:
type: string
ipv6_interface_type:
type: string
ipv6_pd_auto_prefixid_enabled:
type: boolean
ipv6_ra_enabled:
type: boolean
ipv6_setting_preference:
type: string
ipv6_subnet:
type: string
name:
type: string
networkgroup:
type: string
purpose:
type: string
setting_preference:
type: string
vlan:
format: int64
type: integer
vlan_enabled:
type: boolean
required:
- name
type: object
status:
description: NetworkconfigurationStatus defines the observed state of
Networkconfiguration.
properties:
firewall_zone_id:
description: |-
INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
Important: Run "make" to regenerate code after modifying this file
type: string
ipv6_subnet_status:
type: string
lastSyncTime:
description: LastSyncTime is the last time the object was synced
format: date-time
type: string
resources_managed:
properties:
networks_managed:
items:
properties:
id:
type: string
name:
type: string
type: object
type: array
type: object
syncedWithUnifi:
description: SyncedWithUnifi indicates whether the addresses are successfully
pushed
type: boolean
type: object
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: portforwards.unifi.engen.priv.no
spec:
group: unifi.engen.priv.no
names:
kind: PortForward
listKind: PortForwardList
plural: portforwards
singular: portforward
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: |-
PortForward is a placeholder type to allow future CRD support if needed.
Right now, port forwards are managed entirely through annotations on Services.
properties:
apiVersion:
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
kind:
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
metadata:
type: object
spec:
type: object
status:
type: object
type: object
served: true
storage: true
subresources:
status: {}
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-controller-manager
namespace: unifi-network-operator-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-leader-election-role
namespace: unifi-network-operator-system
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-firewallpolicy-admin-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallpolicies
verbs:
- '*'
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallpolicies/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-firewallpolicy-editor-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallpolicies
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallpolicies/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-firewallpolicy-viewer-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallpolicies
verbs:
- get
- list
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallpolicies/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-firewallzone-admin-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallzones
verbs:
- '*'
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallzones/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-firewallzone-editor-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallzones
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallzones/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-firewallzone-viewer-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallzones
verbs:
- get
- list
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallzones/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: unifi-network-operator-manager-role
rules:
- apiGroups:
- ""
resources:
- configmaps
- services
verbs:
- get
- list
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallgroups
- firewallpolicies
- firewallzones
- networkconfigurations
- portforwards
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallgroups/finalizers
- firewallpolicies/finalizers
- firewallzones/finalizers
- networkconfigurations/finalizers
- portforwards/finalizers
verbs:
- update
- apiGroups:
- unifi.engen.priv.no
resources:
- firewallgroups/status
- firewallpolicies/status
- firewallzones/status
- networkconfigurations/status
- portforwards/status
verbs:
- get
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: unifi-network-operator-metrics-auth-role
rules:
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: unifi-network-operator-metrics-reader
rules:
- nonResourceURLs:
- /metrics
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-networkconfiguration-admin-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- networkconfigurations
verbs:
- '*'
- apiGroups:
- unifi.engen.priv.no
resources:
- networkconfigurations/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-networkconfiguration-editor-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- networkconfigurations
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- networkconfigurations/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-networkconfiguration-viewer-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- networkconfigurations
verbs:
- get
- list
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- networkconfigurations/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-portforward-admin-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards
verbs:
- '*'
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-portforward-editor-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-portforward-viewer-role
rules:
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards
verbs:
- get
- list
- watch
- apiGroups:
- unifi.engen.priv.no
resources:
- portforwards/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-leader-election-rolebinding
namespace: unifi-network-operator-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: unifi-network-operator-leader-election-role
subjects:
- kind: ServiceAccount
name: unifi-network-operator-controller-manager
namespace: unifi-network-operator-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
name: unifi-network-operator-manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: unifi-network-operator-manager-role
subjects:
- kind: ServiceAccount
name: unifi-network-operator-controller-manager
namespace: unifi-network-operator-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: unifi-network-operator-metrics-auth-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: unifi-network-operator-metrics-auth-role
subjects:
- kind: ServiceAccount
name: unifi-network-operator-controller-manager
namespace: unifi-network-operator-system
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
control-plane: controller-manager
name: unifi-network-operator-controller-manager-metrics-service
namespace: unifi-network-operator-system
spec:
ports:
- name: https
port: 8443
protocol: TCP
targetPort: 8443
selector:
app.kubernetes.io/name: unifi-network-operator
control-plane: controller-manager
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: unifi-network-operator
control-plane: controller-manager
name: unifi-network-operator-controller-manager
namespace: unifi-network-operator-system
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: unifi-network-operator
control-plane: controller-manager
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: manager
labels:
app.kubernetes.io/name: unifi-network-operator
control-plane: controller-manager
spec:
containers:
- args:
- --metrics-bind-address=:8443
- --leader-elect
- --health-probe-bind-address=:8081
env:
- name: UNIFI_URL
valueFrom:
secretKeyRef:
key: UNIFI_URL
name: unifi-configuration
- name: UNIFI_SITE
valueFrom:
secretKeyRef:
key: UNIFI_SITE
name: unifi-configuration
- name: UNIFI_USER
valueFrom:
secretKeyRef:
key: UNIFI_USERNAME
name: unifi-configuration
- name: UNIFI_PASSWORD
valueFrom:
secretKeyRef:
key: UNIFI_PASSWORD
name: unifi-configuration
image: gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller:latest
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
name: manager
ports: []
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts: []
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
serviceAccountName: unifi-network-operator-controller-manager
terminationGracePeriodSeconds: 10
volumes: []

347
go.mod
View File

@@ -1,15 +1,14 @@
module github.com/vegardengen/unifi-network-operator module gitea.engen.priv.no/klauvsteinen/unifi-network-operator
go 1.24.0 go 1.24.0
toolchain go1.24.1 toolchain go1.24.1
godebug default=go1.23
require ( require (
github.com/onsi/ginkgo/v2 v2.23.4 github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/gomega v1.37.0 github.com/onsi/gomega v1.37.0
github.com/vegardengen/go-unifi v0.0.1-alpha25 gitea.engen.priv.no/klauvsteinen/go-unifi v0.0.1-alpha26
k8s.io/api v0.32.1 k8s.io/api v0.32.1
k8s.io/apimachinery v0.32.1 k8s.io/apimachinery v0.32.1
k8s.io/client-go v0.32.1 k8s.io/client-go v0.32.1
@@ -17,376 +16,54 @@ require (
) )
require ( require (
4d63.com/gocheckcompilerdirectives v1.2.1 // indirect
4d63.com/gochecknoglobals v0.2.1 // indirect
cel.dev/expr v0.23.1 // indirect cel.dev/expr v0.23.1 // indirect
cloud.google.com/go v0.112.0 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.1.5 // indirect
cloud.google.com/go/kms v1.15.5 // indirect
cloud.google.com/go/storage v1.36.0 // indirect
code.gitea.io/sdk/gitea v0.16.0 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/4meepo/tagalign v1.3.3 // indirect
github.com/Abirdcfly/dupword v0.0.13 // indirect
github.com/AlekSi/pointer v1.2.0 // indirect
github.com/Antonboom/errname v0.1.12 // indirect
github.com/Antonboom/nilnil v0.1.7 // indirect
github.com/Antonboom/testifylint v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.4.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys v0.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
github.com/GaijinEntertainment/go-exhaustruct/v3 v3.1.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/OpenPeeDeeP/depguard/v2 v2.1.0 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/alecthomas/go-check-sumtype v0.1.3 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
github.com/alexkohler/nakedret/v2 v2.0.2 // indirect
github.com/alexkohler/prealloc v1.0.0 // indirect
github.com/alingse/asasalint v0.0.11 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/ashanbrown/forbidigo v1.6.0 // indirect
github.com/ashanbrown/makezero v1.1.1 // indirect
github.com/atc0005/go-teams-notify/v2 v2.8.0 // indirect
github.com/aws/aws-sdk-go v1.47.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.21.2 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.13 // indirect
github.com/aws/aws-sdk-go-v2/config v1.19.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.13.43 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.76 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ecr v1.20.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.14 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.36 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.4 // indirect
github.com/aws/aws-sdk-go-v2/service/kms v1.24.7 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.40.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 // indirect
github.com/aws/smithy-go v1.15.0 // indirect
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/bkielbasa/cyclop v1.2.1 // indirect
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect
github.com/blang/semver/v4 v4.0.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect
github.com/blizzy78/varnamelen v0.8.0 // indirect
github.com/bombsimon/wsl/v3 v3.4.0 // indirect
github.com/breml/bidichk v0.2.7 // indirect
github.com/breml/errchkjson v0.3.6 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/butuzov/ireturn v0.2.2 // indirect
github.com/butuzov/mirror v1.1.0 // indirect
github.com/caarlos0/ctrlc v1.2.0 // indirect
github.com/caarlos0/env/v9 v9.0.0 // indirect
github.com/caarlos0/go-reddit/v3 v3.0.1 // indirect
github.com/caarlos0/go-shellwords v1.0.12 // indirect
github.com/caarlos0/go-version v0.1.1 // indirect
github.com/caarlos0/log v0.4.2 // indirect
github.com/catenacyber/perfsprint v0.2.0 // indirect
github.com/cavaliergopher/cpio v1.0.1 // indirect
github.com/ccojocar/zxcvbn-go v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/charithe/durationcheck v0.0.10 // indirect
github.com/charmbracelet/lipgloss v0.8.0 // indirect
github.com/chavacava/garif v0.1.0 // indirect
github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect
github.com/cloudflare/circl v1.3.5 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/curioswitch/go-reassign v0.2.0 // indirect
github.com/daixiang0/gci v0.11.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/denis-tingaikin/go-header v0.4.3 // indirect
github.com/dghubble/go-twitter v0.0.0-20211115160449-93a8679adecb // indirect
github.com/dghubble/oauth1 v0.7.2 // indirect
github.com/dghubble/sling v1.4.0 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/disgoorg/disgo v0.16.9 // indirect
github.com/disgoorg/json v1.1.0 // indirect
github.com/disgoorg/log v1.2.1 // indirect
github.com/disgoorg/snowflake/v2 v2.0.1 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/cli v24.0.7+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/elliotchance/orderedmap/v2 v2.2.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/esimonov/ifshort v1.0.4 // indirect
github.com/ettle/strcase v0.1.1 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fatih/structtag v1.2.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/firefart/nonamedreturns v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fxamacker/cbor/v2 v2.8.0 // indirect github.com/fxamacker/cbor/v2 v2.8.0 // indirect
github.com/fzipp/gocyclo v0.6.0 // indirect
github.com/ghostiam/protogetter v0.2.3 // indirect
github.com/go-critic/go-critic v0.9.0 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-git/go-git/v5 v5.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-logr/zapr v1.3.0 // indirect github.com/go-logr/zapr v1.3.0 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
github.com/go-openapi/errors v0.20.4 // indirect
github.com/go-openapi/jsonpointer v0.21.1 // indirect github.com/go-openapi/jsonpointer v0.21.1 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/loads v0.21.2 // indirect
github.com/go-openapi/runtime v0.26.0 // indirect
github.com/go-openapi/spec v0.20.9 // indirect
github.com/go-openapi/strfmt v0.21.7 // indirect
github.com/go-openapi/swag v0.23.1 // indirect github.com/go-openapi/swag v0.23.1 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect
github.com/go-toolsmith/astcast v1.1.0 // indirect
github.com/go-toolsmith/astcopy v1.1.0 // indirect
github.com/go-toolsmith/astequal v1.1.0 // indirect
github.com/go-toolsmith/astfmt v1.1.0 // indirect
github.com/go-toolsmith/astp v1.1.0 // indirect
github.com/go-toolsmith/strparse v1.1.0 // indirect
github.com/go-toolsmith/typep v1.1.0 // indirect
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect
github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect
github.com/golangci/gofmt v0.0.0-20231018234816-f50ced29576e // indirect
github.com/golangci/golangci-lint v1.55.2 // indirect
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 // indirect
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca // indirect
github.com/golangci/misspell v0.4.1 // indirect
github.com/golangci/revgrep v0.5.2 // indirect
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect
github.com/google/btree v1.1.3 // indirect github.com/google/btree v1.1.3 // indirect
github.com/google/cel-go v0.22.0 // indirect github.com/google/cel-go v0.22.0 // indirect
github.com/google/gnostic-models v0.6.9 // indirect github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
github.com/google/go-containerregistry v0.16.1 // indirect
github.com/google/go-github/v55 v55.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect github.com/google/gofuzz v1.2.0 // indirect
github.com/google/ko v0.14.1 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/rpmpack v0.5.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/google/wire v0.5.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect
github.com/goreleaser/chglog v0.5.0 // indirect
github.com/goreleaser/fileglob v1.3.0 // indirect
github.com/goreleaser/goreleaser v1.21.2 // indirect
github.com/goreleaser/nfpm/v2 v2.33.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
github.com/gostaticanalysis/comment v1.4.2 // indirect
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/invopop/jsonschema v0.9.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jgautheron/goconst v1.6.0 // indirect
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/julz/importas v0.1.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/kisielk/errcheck v1.6.3 // indirect
github.com/kisielk/gotool v1.0.0 // indirect
github.com/kkHAIKE/contextcheck v1.1.4 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/kulti/thelper v0.6.3 // indirect
github.com/kunwardeep/paralleltest v1.0.8 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/kyoh86/exportloopref v0.1.11 // indirect
github.com/ldez/gomoddirectives v0.2.3 // indirect
github.com/ldez/tagliatelle v0.5.0 // indirect
github.com/leonklingele/grouper v1.1.1 // indirect
github.com/letsencrypt/boulder v0.0.0-20231026200631-000cd05d5491 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufeee/execinquery v1.2.1 // indirect
github.com/macabu/inamedparam v0.1.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.9.0 // indirect github.com/mailru/easyjson v0.9.0 // indirect
github.com/maratori/testableexamples v1.0.0 // indirect
github.com/maratori/testpackage v1.1.1 // indirect
github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-mastodon v0.0.6 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
github.com/mgechev/revive v1.3.4 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/moricho/tparallel v0.3.1 // indirect
github.com/muesli/mango v0.1.0 // indirect
github.com/muesli/mango-cobra v1.2.0 // indirect
github.com/muesli/mango-pflag v0.1.0 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/roff v0.1.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nakabonne/nestif v0.3.1 // indirect
github.com/nishanths/exhaustive v0.11.0 // indirect
github.com/nishanths/predeclared v0.2.2 // indirect
github.com/nunnatsa/ginkgolinter v0.14.1 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/polyfloyd/go-errorlint v1.4.5 // indirect
github.com/prometheus/client_golang v1.22.0 // indirect github.com/prometheus/client_golang v1.22.0 // indirect
github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.63.0 // indirect github.com/prometheus/common v0.63.0 // indirect
github.com/prometheus/procfs v0.16.0 // indirect github.com/prometheus/procfs v0.16.0 // indirect
github.com/quasilyte/go-ruleguard v0.4.0 // indirect
github.com/quasilyte/gogrep v0.5.0 // indirect
github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
github.com/rivo/uniseg v0.4.2 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/ryancurrah/gomodguard v1.3.0 // indirect
github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect
github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect
github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
github.com/sashamelentyev/usestdlibvars v1.24.0 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.7.0 // indirect
github.com/securego/gosec/v2 v2.18.2 // indirect
github.com/sergi/go-diff v1.2.0 // indirect
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sigstore/cosign/v2 v2.2.1 // indirect
github.com/sigstore/rekor v1.3.3 // indirect
github.com/sigstore/sigstore v1.7.5 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sivchari/containedctx v1.0.3 // indirect
github.com/sivchari/nosnakecase v1.7.0 // indirect
github.com/sivchari/tenv v1.7.1 // indirect
github.com/skeema/knownhosts v1.1.1 // indirect
github.com/slack-go/slack v0.12.3 // indirect
github.com/sonatard/noctx v0.0.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/sourcegraph/go-diff v0.7.0 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/cobra v1.9.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/spf13/viper v1.17.0 // indirect
github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
github.com/tdakkota/asciicheck v0.2.0 // indirect
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
github.com/tetafro/godot v1.4.15 // indirect
github.com/timakin/bodyclose v0.0.0-20230421092635-574207250966 // indirect
github.com/timonwong/loggercheck v0.9.4 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/ultraware/funlen v0.1.0 // indirect
github.com/ultraware/whitespace v0.0.5 // indirect
github.com/uudashr/gocognit v1.1.2 // indirect
github.com/vbatts/tar-split v0.11.5 // indirect
github.com/withfig/autocomplete-tools/integrations/cobra v1.2.1 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/xanzy/go-gitlab v0.93.2 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xen0n/gosmopolitan v1.2.2 // indirect
github.com/yagipy/maintidx v1.0.0 // indirect
github.com/yeya24/promlinter v0.2.0 // indirect
github.com/ykadowak/zerologlint v0.1.3 // indirect
gitlab.com/bosi/decorder v0.4.1 // indirect
gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect
go-simpler.org/sloglint v0.1.2 // indirect
go.mongodb.org/mongo-driver v1.12.1 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
@@ -395,15 +72,10 @@ require (
go.opentelemetry.io/otel/sdk v1.35.0 // indirect go.opentelemetry.io/otel/sdk v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.tmz.dev/musttag v0.7.2 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect go.uber.org/zap v1.27.0 // indirect
gocloud.dev v0.34.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/net v0.39.0 // indirect golang.org/x/net v0.39.0 // indirect
golang.org/x/oauth2 v0.29.0 // indirect golang.org/x/oauth2 v0.29.0 // indirect
golang.org/x/sync v0.13.0 // indirect golang.org/x/sync v0.13.0 // indirect
@@ -412,37 +84,22 @@ require (
golang.org/x/text v0.24.0 // indirect golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.11.0 // indirect golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.32.0 // indirect golang.org/x/tools v0.32.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
google.golang.org/api v0.155.0 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250409194420-de1ac958c67a // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect
google.golang.org/grpc v1.71.1 // indirect google.golang.org/grpc v1.71.1 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/mail.v2 v2.3.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
honnef.co/go/tools v0.4.6 // indirect
k8s.io/apiextensions-apiserver v0.32.1 // indirect k8s.io/apiextensions-apiserver v0.32.1 // indirect
k8s.io/apiserver v0.32.1 // indirect k8s.io/apiserver v0.32.1 // indirect
k8s.io/component-base v0.32.1 // indirect k8s.io/component-base v0.32.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect
mvdan.cc/gofumpt v0.5.0 // indirect
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.32.0 // indirect sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.32.0 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/kind v0.20.0 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect sigs.k8s.io/yaml v1.4.0 // indirect

1477
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -38,10 +38,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
// "sigs.k8s.io/controller-runtime/pkg/source" // "sigs.k8s.io/controller-runtime/pkg/source"
goUnifi "github.com/vegardengen/go-unifi/unifi" goUnifi "gitea.engen.priv.no/klauvsteinen/go-unifi/unifi"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
) )
const firewallGroupFinalizer = "finalizer.unifi.engen.priv.no/firewallgroup" const firewallGroupFinalizer = "finalizer.unifi.engen.priv.no/firewallgroup"
@@ -361,10 +361,10 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
log.Error(err, "Could not list network objects") log.Error(err, "Could not list network objects")
return reconcile.Result{}, err return reconcile.Result{}, err
} }
ipv4_name := "k8s-" + firewallGroup.Spec.Name + "-ipv4" ipv4_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-ipv4"
ipv6_name := "k8s-" + firewallGroup.Spec.Name + "-ipv6" ipv6_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-ipv6"
tcpports_name := "k8s-" + firewallGroup.Spec.Name + "-tcpports" tcpports_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-tcpports"
udpports_name := "k8s-" + firewallGroup.Spec.Name + "-udpports" udpports_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-udpports"
ipv4_done := false ipv4_done := false
ipv6_done := false ipv6_done := false
tcpports_done := false tcpports_done := false
@@ -372,12 +372,12 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
for _, firewall_group := range firewall_groups { for _, firewall_group := range firewall_groups {
if firewall_group.Name == ipv4_name { if firewall_group.Name == ipv4_name {
if len(ipv4) == 0 { if len(ipv4) == 0 {
log.Info(fmt.Sprintf("Delete %s", ipv4_name)) log.Info(fmt.Sprintf("Delete %s: %s", ipv4_name, firewallGroup.Status.ResourcesManaged.IPV4Object.ID))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.IPV4Object.ID)
if err != nil { if err != nil {
msg := strings.ToLower(err.Error()) msg := strings.ToLower(err.Error())
log.Info(msg) log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") { if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!") log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"127.0.0.1"} firewall_group.GroupMembers = []string{"127.0.0.1"}
firewall_group.Name = firewall_group.Name + "-deleted" firewall_group.Name = firewall_group.Name + "-deleted"
@@ -413,11 +413,11 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if firewall_group.Name == ipv6_name { if firewall_group.Name == ipv6_name {
if len(ipv6) == 0 { if len(ipv6) == 0 {
log.Info(fmt.Sprintf("Delete %s", ipv6_name)) log.Info(fmt.Sprintf("Delete %s", ipv6_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.IPV6Object.ID)
if err != nil { if err != nil {
msg := strings.ToLower(err.Error()) msg := strings.ToLower(err.Error())
log.Info(msg) log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") { if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!") log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"::1"} firewall_group.GroupMembers = []string{"::1"}
firewall_group.Name = firewall_group.Name + "-deleted" firewall_group.Name = firewall_group.Name + "-deleted"
@@ -453,11 +453,11 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if firewall_group.Name == tcpports_name { if firewall_group.Name == tcpports_name {
if len(tcpports) == 0 { if len(tcpports) == 0 {
log.Info(fmt.Sprintf("Delete %s", tcpports_name)) log.Info(fmt.Sprintf("Delete %s", tcpports_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID)
if err != nil { if err != nil {
msg := strings.ToLower(err.Error()) msg := strings.ToLower(err.Error())
log.Info(msg) log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") { if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!") log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"0"} firewall_group.GroupMembers = []string{"0"}
firewall_group.Name = firewall_group.Name + "-deleted" firewall_group.Name = firewall_group.Name + "-deleted"
@@ -493,11 +493,11 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if firewall_group.Name == udpports_name { if firewall_group.Name == udpports_name {
if len(udpports) == 0 { if len(udpports) == 0 {
log.Info(fmt.Sprintf("Delete %s", udpports_name)) log.Info(fmt.Sprintf("Delete %s", udpports_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID)
if err != nil { if err != nil {
msg := strings.ToLower(err.Error()) msg := strings.ToLower(err.Error())
log.Info(msg) log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") { if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!") log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"127.0.0.1"} firewall_group.GroupMembers = []string{"127.0.0.1"}
firewall_group.Name = firewall_group.Name + "-deleted" firewall_group.Name = firewall_group.Name + "-deleted"

View File

@@ -27,7 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
) )
var _ = Describe("FirewallGroup Controller", func() { var _ = Describe("FirewallGroup Controller", func() {

View File

@@ -33,10 +33,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
goUnifi "github.com/vegardengen/go-unifi/unifi" goUnifi "gitea.engen.priv.no/klauvsteinen/go-unifi/unifi"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
) )
// FirewallPolicyReconciler reconciles a FirewallPolicy object // FirewallPolicyReconciler reconciles a FirewallPolicy object
@@ -468,7 +468,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if len(firewallGroup.Status.ResolvedIPV4Addresses) > 0 { if len(firewallGroup.Status.ResolvedIPV4Addresses) > 0 {
if len(firewallGroup.Status.ResolvedTCPPorts) > 0 { if len(firewallGroup.Status.ResolvedTCPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv4-tcp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv4-tcp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv4 tcp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv4 tcp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -503,7 +503,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
} }
if len(firewallGroup.Status.ResolvedUDPPorts) > 0 { if len(firewallGroup.Status.ResolvedUDPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv4-udp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv4-udp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv4 udp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv4 udp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -541,7 +541,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
if len(firewallGroup.Status.ResolvedIPV6Addresses) > 0 { if len(firewallGroup.Status.ResolvedIPV6Addresses) > 0 {
if len(firewallGroup.Status.ResolvedTCPPorts) > 0 { if len(firewallGroup.Status.ResolvedTCPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv6-tcp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv6-tcp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv6 tcp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv6 tcp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -577,7 +577,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
} }
if len(firewallGroup.Status.ResolvedUDPPorts) > 0 { if len(firewallGroup.Status.ResolvedUDPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv6-udp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "zone:" + zoneCRDs.Items[zoneIndex].Name + "-" + firewallGroup.Name + "-ipv6-udp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv6 udp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv6 udp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -640,7 +640,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
if len(firewallGroup.Status.ResolvedIPV4Addresses) > 0 { if len(firewallGroup.Status.ResolvedIPV4Addresses) > 0 {
if len(firewallGroup.Status.ResolvedTCPPorts) > 0 { if len(firewallGroup.Status.ResolvedTCPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv4-tcp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv4-tcp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv4 tcp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv4 tcp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -677,7 +677,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
} }
if len(firewallGroup.Status.ResolvedUDPPorts) > 0 { if len(firewallGroup.Status.ResolvedUDPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv4-udp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv4-udp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv4 udp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv4 udp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -716,7 +716,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
if len(firewallGroup.Status.ResolvedIPV6Addresses) > 0 { if len(firewallGroup.Status.ResolvedIPV6Addresses) > 0 {
if len(firewallGroup.Status.ResolvedTCPPorts) > 0 { if len(firewallGroup.Status.ResolvedTCPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv6-tcp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv6-tcp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv6 tcp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv6 tcp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()
@@ -753,7 +753,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
} }
} }
if len(firewallGroup.Status.ResolvedUDPPorts) > 0 { if len(firewallGroup.Status.ResolvedUDPPorts) > 0 {
policyname := "k8s-fw-" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv6-udp" policyname := "k8s-fw-" + firewallPolicy.Namespace + "/" + firewallPolicy.Name + "-" + "network:" + networkCRDs.Items[networkIndex].Name + "-" + firewallGroup.Name + "-ipv6-udp"
if _, found := unifiFirewallpolicyNames[policyname]; !found { if _, found := unifiFirewallpolicyNames[policyname]; !found {
log.Info(fmt.Sprintf("Creating ipv6 udp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname)) log.Info(fmt.Sprintf("Creating ipv6 udp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy() unifiFirewallPolicy := fillDefaultPolicy()

View File

@@ -27,7 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
) )
var _ = Describe("FirewallPolicy Controller", func() { var _ = Describe("FirewallPolicy Controller", func() {

View File

@@ -28,9 +28,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
) )
// FirewallZoneReconciler reconciles a FirewallZone object // FirewallZoneReconciler reconciles a FirewallZone object

View File

@@ -27,7 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
) )
var _ = Describe("FirewallZone Controller", func() { var _ = Describe("FirewallZone Controller", func() {

View File

@@ -19,6 +19,7 @@ package controller
import ( import (
"context" "context"
"fmt" "fmt"
"reflect"
"time" "time"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@@ -27,9 +28,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log"
unifiv1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi" "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
) )
// NetworkconfigurationReconciler reconciles a Networkconfiguration object // NetworkconfigurationReconciler reconciles a Networkconfiguration object
@@ -111,10 +112,12 @@ func (r *NetworkconfigurationReconciler) Reconcile(ctx context.Context, req ctrl
Vlan: int64(unifinetwork.VLAN), Vlan: int64(unifinetwork.VLAN),
VlanEnabled: unifinetwork.VLANEnabled, VlanEnabled: unifinetwork.VLANEnabled,
} }
networkObj.Spec = networkSpec if !reflect.DeepEqual(networkObj.Spec, networkSpec) {
err := r.Update(ctx, &networkObj) networkObj.Spec = networkSpec
if err != nil { err := r.Update(ctx, &networkObj)
return ctrl.Result{}, err if err != nil {
return ctrl.Result{}, err
}
} }
} }
} }
@@ -210,14 +213,19 @@ func (r *NetworkconfigurationReconciler) Reconcile(ctx context.Context, req ctrl
} else { } else {
for _, networkCRD := range networkCRDs.Items { for _, networkCRD := range networkCRDs.Items {
if networkCRD.Spec.Name == unifinetwork.Name { if networkCRD.Spec.Name == unifinetwork.Name {
networkCRD.Spec = networkSpec if !reflect.DeepEqual(networkCRD.Spec, networkSpec) {
} networkCRD.Spec = networkSpec
err := r.Update(ctx, &networkCRD) err := r.Update(ctx, &networkCRD)
if err != nil { if err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} }
if err = r.Status().Update(ctx, &networkCRD); err != nil { }
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err if !reflect.DeepEqual(networkCRD.Status, networkStatus) {
networkCRD.Status = networkStatus
if err = r.Status().Update(ctx, &networkCRD); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
} }
} }
} }

View File

@@ -27,7 +27,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
) )
var _ = Describe("Networkconfiguration Controller", func() { var _ = Describe("Networkconfiguration Controller", func() {

View File

@@ -0,0 +1,152 @@
package controller
import (
"context"
"fmt"
"strconv"
"strings"
"time"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
// "k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
// "sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
// "sigs.k8s.io/controller-runtime/pkg/reconcile"
// "sigs.k8s.io/controller-runtime/pkg/source"
goUnifi "gitea.engen.priv.no/klauvsteinen/go-unifi/unifi"
// unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
"gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/config"
"gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
)
type PortForwardReconciler struct {
client.Client
Scheme *runtime.Scheme
UnifiClient *unifi.UnifiClient
ConfigLoader *config.ConfigLoaderType
}
// +kubebuilder:rbac:groups=unifi.engen.priv.no,resources=portforwards,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=unifi.engen.priv.no,resources=portforwards/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=unifi.engen.priv.no,resources=portforwards/finalizers,verbs=update
// +kubebuilder:rbac:groups="",resources=services,verbs=list;get;watch
// +kubebuilder:rbac:groups="",resources=configmaps,verbs=list;get;watch
func (r *PortForwardReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
var svc corev1.Service
if err := r.Get(ctx, req.NamespacedName, &svc); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
annotation := svc.Annotations["portforward.unifi.engen.priv.no/forward"]
err := r.UnifiClient.Reauthenticate()
if err != nil {
log.Error(err, "Failed to authenticate to Unifi")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
portforwards, err := r.UnifiClient.Client.ListPortForward(context.Background(), r.UnifiClient.SiteID)
if err != nil {
log.Error(err, "Failed to list PortForfards")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
portforwardnames := make(map[string]int)
for i, portforward := range portforwards {
portforwardnames[portforward.Name] = i
}
if annotation == "" {
for _, port := range svc.Spec.Ports {
portforwardname := "k8s-forward-" + svc.Name + "-" + port.Name
if i, found := portforwardnames[portforwardname]; found {
log.Info(fmt.Sprintf("Cleaning up old portfoward for service %s/%s", svc.Namespace, svc.Name))
if err := r.UnifiClient.Client.DeletePortForward(context.Background(), r.UnifiClient.SiteID, portforwards[i].ID); err != nil {
log.Error(err, "Could not delete portforward")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
return ctrl.Result{}, nil
}
portMap := make(map[string]int)
entries := strings.Split(annotation, ";")
for _, entry := range entries {
entry = strings.TrimSpace(entry)
if entry == "" {
continue
}
parts := strings.Split(entry, ":")
for _, port := range svc.Spec.Ports {
if parts[0] == port.Name {
if len(parts) == 1 {
portMap[parts[0]] = int(port.Port)
} else if len(parts) == 2 {
extPort, err := strconv.Atoi(parts[1])
if err != nil {
log.Error(err, "Invalid external port", "entry", entry)
continue
}
portMap[parts[0]] = extPort
}
}
}
}
if len(svc.Status.LoadBalancer.Ingress) == 0 {
log.Info("No LoadBalancer IP for Service", "service", svc.Name)
return ctrl.Result{}, nil
}
ip := svc.Status.LoadBalancer.Ingress[0].IP
for _, port := range svc.Spec.Ports {
extPort, found := portMap[port.Name]
if found {
log.Info("Setting up port forward",
"externalPort", extPort,
"internalPort", port.Port,
"ip", ip,
"protocol", port.Protocol)
}
portforwardname := "k8s-forward-" + svc.Name + "-" + port.Name
log.Info(fmt.Sprintf("Should handle %s", portforwardname))
if portforwardindex, found := portforwardnames[portforwardname]; found {
if portforwards[portforwardindex].DstPort == fmt.Sprintf("%d", portMap[port.Name]) && portforwards[portforwardindex].Fwd == ip && portforwards[portforwardindex].FwdPort == fmt.Sprintf("%d", port.Port) {
log.Info("Portforward already exists and is correct")
} else {
log.Info("Exists, but need to update")
portforwards[portforwardindex].DstPort = fmt.Sprintf("%d", portMap[port.Name])
portforwards[portforwardindex].FwdPort = fmt.Sprintf("%d", port.Port)
portforwards[portforwardindex].Fwd = ip
if _, err := r.UnifiClient.Client.UpdatePortForward(context.Background(), r.UnifiClient.SiteID, &portforwards[portforwardindex]); err != nil {
log.Error(err, fmt.Sprintf("Failed to update portforward %s", portforwardname))
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
} else {
_, err := r.UnifiClient.Client.CreatePortForward(context.Background(), r.UnifiClient.SiteID, &goUnifi.PortForward{Name: portforwardname, PfwdInterface: "wan", Src: "any", Log: false, DestinationIPs: []goUnifi.PortForwardDestinationIPs{}, Enabled: true, Fwd: ip, DestinationIP: "any", Proto: "tcp", DstPort: fmt.Sprintf("%d", portMap[port.Name]), SiteID: r.UnifiClient.SiteID, FwdPort: fmt.Sprintf("%d", port.Port)})
if err != nil {
log.Error(err, "Portforward could not be created")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
return ctrl.Result{}, nil
}
func (r *PortForwardReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.Service{}).
WithOptions(controller.Options{MaxConcurrentReconciles: 1}).
Complete(r)
}

View File

@@ -0,0 +1,84 @@
/*
Copyright 2025 Vegard Engen.
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 controller
import (
"context"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
)
var _ = Describe("PortForward Controller", func() {
Context("When reconciling a resource", func() {
const resourceName = "test-resource"
ctx := context.Background()
typeNamespacedName := types.NamespacedName{
Name: resourceName,
Namespace: "default", // TODO(user):Modify as needed
}
portforward := &unifiv1beta1.PortForward{}
BeforeEach(func() {
By("creating the custom resource for the Kind PortForward")
err := k8sClient.Get(ctx, typeNamespacedName, portforward)
if err != nil && errors.IsNotFound(err) {
resource := &unifiv1beta1.PortForward{
ObjectMeta: metav1.ObjectMeta{
Name: resourceName,
Namespace: "default",
},
// TODO(user): Specify other spec details if needed.
}
Expect(k8sClient.Create(ctx, resource)).To(Succeed())
}
})
AfterEach(func() {
// TODO(user): Cleanup logic after each test, like removing the resource instance.
resource := &unifiv1beta1.PortForward{}
err := k8sClient.Get(ctx, typeNamespacedName, resource)
Expect(err).NotTo(HaveOccurred())
By("Cleanup the specific resource instance PortForward")
Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
})
It("should successfully reconcile the resource", func() {
By("Reconciling the created resource")
controllerReconciler := &PortForwardReconciler{
Client: k8sClient,
Scheme: k8sClient.Scheme(),
}
_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
NamespacedName: typeNamespacedName,
})
Expect(err).NotTo(HaveOccurred())
// TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
// Example: If you expect a certain status condition after reconciliation, verify it here.
})
})
})

View File

@@ -32,7 +32,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log" logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/log/zap"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" unifiv1beta1 "gitea.engen.priv.no/klauvsteinen/unifi-network-operator/api/v1beta1"
// +kubebuilder:scaffold:imports // +kubebuilder:scaffold:imports
) )

View File

@@ -13,7 +13,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/vegardengen/go-unifi/unifi" "gitea.engen.priv.no/klauvsteinen/go-unifi/unifi"
) )
type UnifiClient struct { type UnifiClient struct {

7
ko.yaml Normal file
View File

@@ -0,0 +1,7 @@
defaultBaseImage: cgr.dev/chainguard/static:latest
labels:
org.opencontainers.image.authors: Vegard Engen <vegard@engen.priv.no>
org.opencontainers.image.source: https://gitea.engen.priv.no/klauvsteinen/unifi-network-operator
org.opencontainers.image.vendor: Klauvsteinen
dev.chainguard.package.main: ""