Compare commits

...

156 Commits

Author SHA1 Message Date
ea68bed9c2 Add helm
All checks were successful
Build project / build (push) Successful in 4m43s
2025-10-21 07:23:07 +02:00
32a595d160 Merge pull request 'Handle services in same namespace if namespace is not specified' (#34) from feature/properly-handle-namespaced-services into main
All checks were successful
Publish / build (push) Successful in 2m0s
Reviewed-on: #34
2025-06-28 23:14:01 +00:00
834f52c015 Handle services in same namespace if namespace is not specified
All checks were successful
Build project / build (push) Successful in 1m42s
2025-06-29 01:12:26 +02:00
9d43b517e6 Merge pull request 'Properly check for firewallGroup in same namespace' (#33) from feature/properly-handle-firewallgroups-in-same-namespace into main
All checks were successful
Publish / build (push) Successful in 2m27s
Reviewed-on: #33
2025-06-28 23:07:05 +00:00
2b38f08a1a Merge pull request 'feature/cleanly-delete-empty-resources' (#32) from feature/cleanly-delete-empty-resources into main
Some checks failed
Publish / build (push) Has been cancelled
Reviewed-on: #32
2025-06-28 22:59:42 +00:00
3a63034e26 Properly check for firewallGroup in same namespace
All checks were successful
Build project / build (push) Successful in 1m54s
Publish / build (push) Successful in 2m0s
2025-06-29 00:58:57 +02:00
37d8060995 Check for nil ResourcesManaged
All checks were successful
Build project / build (push) Successful in 2m0s
Publish / build (push) Successful in 2m4s
2025-06-29 00:44:49 +02:00
8623d6cbc0 debug
All checks were successful
Build project / build (push) Successful in 1m52s
Publish / build (push) Successful in 2m2s
2025-06-29 00:24:00 +02:00
61606e8a7e debug 2025-06-29 00:23:26 +02:00
44d89a5a50 Check for nil instead of length
Some checks failed
Build project / build (push) Failing after 1m7s
2025-06-29 00:17:44 +02:00
19f24add0a Check for Status field before checking for managed resources
Some checks failed
Build project / build (push) Failing after 1m9s
Publish / build (push) Failing after 1m20s
2025-06-29 00:11:49 +02:00
2e95d29373 Merge pull request 'Check for firewallGroup in same namespace if namespace is not defined' (#31) from feature/default-namespace-same-as-firewallpolicy-namespace-when-referring-firewallgroup into main
All checks were successful
Publish / build (push) Successful in 2m16s
Reviewed-on: #31
2025-06-28 21:56:08 +00:00
990140ee1c Check for firewallGroup in same namespace if namespace is not defined
All checks were successful
Build project / build (push) Successful in 1m51s
2025-06-28 23:53:51 +02:00
24c88264c9 Merge pull request 'Fix namespace matching for firewallgroups in firewallpolicies' (#30) from feature/default-namespace-same-as-firewallpolicy-namespace-when-referring-firewallgroup into main
All checks were successful
Publish / build (push) Successful in 2m1s
Reviewed-on: #30
2025-06-28 16:38:11 +00:00
938d53fa8f Fix namespace matching for firewallgroups in firewallpolicies
All checks were successful
Build project / build (push) Successful in 1m55s
Publish / build (push) Successful in 2m5s
2025-06-28 18:33:54 +02:00
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
46 changed files with 3328 additions and 110 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
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)
ifeq (,$(shell go env GOBIN))
@@ -8,7 +8,7 @@ else
GOBIN=$(shell go env GOBIN)
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.
# Be aware that the target commands are only tested with Docker which is
@@ -229,3 +229,57 @@ mv $(1) $(1)-$(3) ;\
} ;\
ln -sf $(1)-$(3) $(1)
endef
##@ Helm
HELM_CHART_DIR ?= helm/unifi-network-operator
HELM_RELEASE_NAME ?= unifi-network-operator
HELM_NAMESPACE ?= unifi-network-operator-system
.PHONY: helm-lint
helm-lint: ## Lint the Helm chart
helm lint $(HELM_CHART_DIR) --set unifi.url="https://test.local" --set unifi.password="test"
.PHONY: helm-template
helm-template: ## Render Helm templates for inspection
helm template $(HELM_RELEASE_NAME) $(HELM_CHART_DIR) \
--namespace $(HELM_NAMESPACE) \
--set unifi.url="https://test.local" \
--set unifi.password="test" \
--debug
.PHONY: helm-install
helm-install: ## Install the Helm chart (requires UNIFI_URL and UNIFI_PASSWORD env vars)
@if [ -z "$(UNIFI_URL)" ]; then echo "Error: UNIFI_URL is not set"; exit 1; fi
@if [ -z "$(UNIFI_PASSWORD)" ]; then echo "Error: UNIFI_PASSWORD is not set"; exit 1; fi
helm install $(HELM_RELEASE_NAME) $(HELM_CHART_DIR) \
--namespace $(HELM_NAMESPACE) \
--create-namespace \
--set unifi.url="$(UNIFI_URL)" \
--set unifi.password="$(UNIFI_PASSWORD)" \
--set unifi.site="$(UNIFI_SITE)" \
--set unifi.username="$(UNIFI_USERNAME)"
.PHONY: helm-upgrade
helm-upgrade: ## Upgrade the Helm release
helm upgrade $(HELM_RELEASE_NAME) $(HELM_CHART_DIR) \
--namespace $(HELM_NAMESPACE)
.PHONY: helm-uninstall
helm-uninstall: ## Uninstall the Helm release
helm uninstall $(HELM_RELEASE_NAME) --namespace $(HELM_NAMESPACE)
.PHONY: helm-package
helm-package: ## Package the Helm chart
helm package $(HELM_CHART_DIR) -d dist/
.PHONY: helm-dry-run
helm-dry-run: ## Dry run Helm installation
@if [ -z "$(UNIFI_URL)" ]; then echo "Error: UNIFI_URL is not set"; exit 1; fi
@if [ -z "$(UNIFI_PASSWORD)" ]; then echo "Error: UNIFI_PASSWORD is not set"; exit 1; fi
helm install $(HELM_RELEASE_NAME) $(HELM_CHART_DIR) \
--namespace $(HELM_NAMESPACE) \
--create-namespace \
--set unifi.url="$(UNIFI_URL)" \
--set unifi.password="$(UNIFI_PASSWORD)" \
--dry-run --debug

10
PROJECT
View File

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

View File

@@ -39,10 +39,10 @@ import (
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/controller"
"github.com/vegardengen/unifi-network-operator/internal/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/controller"
"gitea.engen.priv.no/klauvsteinen/unifi-network-operator/internal/unifi"
// +kubebuilder:scaffold:imports
)

View File

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

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: []

5
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
toolchain go1.24.1
godebug default=go1.23
require (
github.com/onsi/ginkgo/v2 v2.23.4
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/apimachinery v0.32.1
k8s.io/client-go v0.32.1

2
go.sum
View File

@@ -1,5 +1,7 @@
cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
gitea.engen.priv.no/klauvsteinen/go-unifi v0.0.1-alpha26 h1:nM5XNYGPCR+6U5ypssm5iuwJrubeKwD2axLZeZXl/EQ=
gitea.engen.priv.no/klauvsteinen/go-unifi v0.0.1-alpha26/go.mod h1:0cA32wEhA7BTHHI4frsPjXFctHkJq9VZe9yrOwVlpQE=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=

298
helm/INSTALL.md Normal file
View File

@@ -0,0 +1,298 @@
# UniFi Network Operator - Helm Installation Guide
## Quick Start
### 1. Install the Helm Chart
The simplest way to install the operator:
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://your-unifi-controller:8443" \
--set unifi.password="your-password"
```
### 2. Verify Installation
```bash
# Check if the operator is running
kubectl get pods -n unifi-network-operator-system
# Check the operator logs
kubectl logs -n unifi-network-operator-system -l app.kubernetes.io/name=unifi-network-operator -f
# Verify CRDs are installed
kubectl get crds | grep unifi.engen.priv.no
```
### 3. Create Your First Resource
Create a FirewallZone:
```bash
cat <<EOF | kubectl apply -f -
apiVersion: unifi.engen.priv.no/v1beta1
kind: FirewallZone
metadata:
name: test-zone
namespace: default
spec:
zoneName: "test-zone"
EOF
```
## Production Installation
For production deployments, create a `values.yaml` file:
```yaml
# production-values.yaml
replicaCount: 1
image:
repository: gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller
tag: "latest"
pullPolicy: IfNotPresent
unifi:
url: "https://unifi.example.com:8443"
site: "default"
username: "operator-user"
# Use existingSecret in production!
existingSecret: "unifi-credentials"
config:
defaultNamespace: "default"
fullSyncZone: "gateway"
fullSyncNetwork: "core"
kubernetesUnifiZone: "kubernetes"
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 50m
memory: 128Mi
metrics:
serviceMonitor:
enabled: true
additionalLabels:
prometheus: kube-prometheus
leaderElection:
enabled: true
nodeSelector:
kubernetes.io/os: linux
tolerations: []
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- unifi-network-operator
topologyKey: kubernetes.io/hostname
```
Create the secret first:
```bash
kubectl create namespace unifi-network-operator-system
kubectl create secret generic unifi-credentials \
--from-literal=UNIFI_URL="https://unifi.example.com:8443" \
--from-literal=UNIFI_SITE="default" \
--from-literal=UNIFI_USERNAME="operator-user" \
--from-literal=UNIFI_PASSWORD="your-secure-password" \
-n unifi-network-operator-system
```
Then install with the values file:
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
-f production-values.yaml
```
## Upgrading
```bash
helm upgrade unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
-f production-values.yaml
```
## Uninstalling
```bash
# Remove the operator (keeps CRDs and CRs by default)
helm uninstall unifi-network-operator -n unifi-network-operator-system
# To also remove CRDs (this will delete all custom resources!)
kubectl delete crds -l app.kubernetes.io/name=unifi-network-operator
```
## Testing Locally
You can test the chart rendering without installing:
```bash
# Render templates
helm template unifi-network-operator ./helm/unifi-network-operator \
--set unifi.url="https://test.local" \
--set unifi.password="test" \
--debug
# Lint the chart
helm lint ./helm/unifi-network-operator \
--set unifi.url="https://test.local" \
--set unifi.password="test"
# Dry run installation
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://test.local" \
--set unifi.password="test" \
--dry-run --debug
```
## Packaging for Distribution
To package the chart for distribution:
```bash
# Package the chart
helm package helm/unifi-network-operator
# This creates: unifi-network-operator-0.1.0.tgz
# Generate index (if hosting a chart repository)
helm repo index .
```
## Common Configuration Scenarios
### Scenario 1: Development Environment
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://192.168.1.1:8443" \
--set unifi.password="admin" \
--set resources.limits.memory="128Mi" \
--set resources.requests.memory="64Mi"
```
### Scenario 2: Multiple Sites
For managing multiple UniFi sites, deploy separate instances:
```bash
# Site 1
helm install unifi-operator-site1 ./helm/unifi-network-operator \
-n unifi-site1 \
--create-namespace \
--set unifi.url="https://unifi-site1.example.com:8443" \
--set unifi.site="site1" \
--set unifi.password="password1"
# Site 2
helm install unifi-operator-site2 ./helm/unifi-network-operator \
-n unifi-site2 \
--create-namespace \
--set unifi.url="https://unifi-site2.example.com:8443" \
--set unifi.site="site2" \
--set unifi.password="password2"
```
### Scenario 3: Using with ArgoCD
Create an ArgoCD Application:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: unifi-network-operator
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourusername/unifi-network-operator
targetRevision: main
path: helm/unifi-network-operator
helm:
values: |
unifi:
existingSecret: unifi-credentials
config:
fullSyncZone: "gateway"
fullSyncNetwork: "core"
metrics:
serviceMonitor:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: unifi-network-operator-system
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
```
## Troubleshooting
### Operator Won't Start
Check the logs:
```bash
kubectl logs -n unifi-network-operator-system \
-l app.kubernetes.io/name=unifi-network-operator
```
### Connection Issues to UniFi Controller
Verify the secret:
```bash
kubectl get secret -n unifi-network-operator-system
kubectl describe secret unifi-network-operator-unifi \
-n unifi-network-operator-system
```
### CRDs Not Installing
Manually install CRDs:
```bash
kubectl apply -f helm/unifi-network-operator/crds/
```
### Resources Not Syncing
Check operator configuration:
```bash
kubectl get configmap -n unifi-network-operator-system
kubectl describe configmap unifi-network-operator-config \
-n unifi-network-operator-system
```
## Additional Resources
- [Helm Chart README](./unifi-network-operator/README.md)
- [Values Reference](./unifi-network-operator/values.yaml)
- [Custom Resource Examples](../config/samples/)

234
helm/README.md Normal file
View File

@@ -0,0 +1,234 @@
# UniFi Network Operator - Helm Chart
This directory contains the Helm chart for deploying the UniFi Network Operator to Kubernetes.
## Quick Links
- **[Installation Guide](./INSTALL.md)** - Detailed installation instructions and examples
- **[Chart Documentation](./unifi-network-operator/README.md)** - Full configuration reference
- **[Values Reference](./unifi-network-operator/values.yaml)** - All configurable values
## Quick Start
```bash
# Install with minimal configuration
helm install unifi-network-operator ./helm/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://your-unifi-controller:8443" \
--set unifi.password="your-password"
```
## Chart Structure
```
helm/unifi-network-operator/
├── Chart.yaml # Chart metadata
├── values.yaml # Default configuration values
├── README.md # Detailed chart documentation
├── .helmignore # Files to ignore when packaging
├── crds/ # Custom Resource Definitions
│ ├── unifi.engen.priv.no_firewallgroups.yaml
│ ├── unifi.engen.priv.no_firewallpolicies.yaml
│ ├── unifi.engen.priv.no_firewallzones.yaml
│ ├── unifi.engen.priv.no_networkconfigurations.yaml
│ └── unifi.engen.priv.no_portforwards.yaml
└── templates/ # Kubernetes resource templates
├── NOTES.txt # Post-installation notes
├── _helpers.tpl # Template helpers
├── deployment.yaml # Operator deployment
├── serviceaccount.yaml # Service account
├── clusterrole.yaml # Cluster-level permissions
├── clusterrolebinding.yaml
├── role.yaml # Namespace-level permissions
├── rolebinding.yaml
├── configmap.yaml # Operator configuration
├── secret.yaml # UniFi credentials
├── service.yaml # Metrics service
└── servicemonitor.yaml # Prometheus integration
```
## Features
- **Secure by Default**: Runs with restricted security context and non-root user
- **Flexible Configuration**: Extensive values for customization
- **Production Ready**: Leader election, resource limits, health checks
- **Monitoring**: Built-in Prometheus ServiceMonitor support
- **GitOps Friendly**: Works with ArgoCD, Flux, and other GitOps tools
- **Credential Management**: Support for external secrets
## Key Configuration Options
### Required Settings
- `unifi.url` - UniFi controller URL (e.g., `https://unifi.example.com:8443`)
- `unifi.password` - UniFi password (or use `unifi.existingSecret`)
### Common Optional Settings
- `unifi.site` - UniFi site ID (default: `default`)
- `unifi.username` - UniFi username (default: `admin`)
- `config.fullSyncZone` - Zone name for bidirectional sync
- `config.fullSyncNetwork` - Network name for bidirectional sync
- `metrics.serviceMonitor.enabled` - Enable Prometheus monitoring
- `resources.*` - Resource limits and requests
## Using Make Targets
The project Makefile includes helpful Helm targets:
```bash
# Lint the chart
make helm-lint
# Render templates (for debugging)
make helm-template
# Install (requires env vars)
export UNIFI_URL="https://unifi.example.com:8443"
export UNIFI_PASSWORD="your-password"
make helm-install
# Upgrade
make helm-upgrade
# Uninstall
make helm-uninstall
# Package the chart
make helm-package
# Dry run
make helm-dry-run
```
## Examples
### Development Installation
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://192.168.1.1:8443" \
--set unifi.password="admin"
```
### Production with Existing Secret
```bash
# Create secret
kubectl create secret generic unifi-creds \
--from-literal=UNIFI_URL="https://unifi.example.com:8443" \
--from-literal=UNIFI_SITE="default" \
--from-literal=UNIFI_USERNAME="operator" \
--from-literal=UNIFI_PASSWORD="secure-password" \
-n unifi-network-operator-system
# Install with secret reference
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--set unifi.existingSecret="unifi-creds"
```
### With Full Sync and Monitoring
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://unifi.example.com:8443" \
--set unifi.password="password" \
--set config.fullSyncZone="gateway" \
--set config.fullSyncNetwork="core" \
--set metrics.serviceMonitor.enabled=true
```
## Upgrading
To upgrade the operator:
```bash
helm upgrade unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system
```
## Uninstalling
```bash
# Remove the operator (CRDs remain)
helm uninstall unifi-network-operator -n unifi-network-operator-system
# Also remove CRDs (WARNING: deletes all custom resources)
kubectl delete crds \
firewallgroups.unifi.engen.priv.no \
firewallpolicies.unifi.engen.priv.no \
firewallzones.unifi.engen.priv.no \
networkconfigurations.unifi.engen.priv.no \
portforwards.unifi.engen.priv.no
```
## Customization
Create a `custom-values.yaml` file:
```yaml
image:
tag: "v1.0.0"
replicaCount: 1
unifi:
existingSecret: "my-unifi-secret"
config:
fullSyncZone: "gateway"
fullSyncNetwork: "core"
kubernetesUnifiZone: "k8s"
resources:
limits:
memory: 256Mi
requests:
memory: 128Mi
metrics:
serviceMonitor:
enabled: true
additionalLabels:
prometheus: kube-prometheus
nodeSelector:
kubernetes.io/os: linux
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
```
Install with:
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
-f custom-values.yaml
```
## Documentation
- **[INSTALL.md](./INSTALL.md)** - Complete installation guide with examples
- **[Chart README](./unifi-network-operator/README.md)** - Full configuration reference
- **[values.yaml](./unifi-network-operator/values.yaml)** - Commented default values
## Support
For issues and questions:
- Check the [Installation Guide](./INSTALL.md)
- Review the [Chart Documentation](./unifi-network-operator/README.md)
- Check operator logs: `kubectl logs -n unifi-network-operator-system -l app.kubernetes.io/name=unifi-network-operator`
## License
This Helm chart is provided under the same license as the UniFi Network Operator project.

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -0,0 +1,16 @@
apiVersion: v2
name: unifi-network-operator
description: A Kubernetes operator for managing UniFi network configurations
type: application
version: 0.1.0
appVersion: "latest"
home: https://github.com/yourusername/unifi-network-operator
maintainers:
- name: Vegar Dengen
keywords:
- unifi
- network
- operator
- firewall
sources:
- https://github.com/yourusername/unifi-network-operator

View File

@@ -0,0 +1,335 @@
# UniFi Network Operator Helm Chart
A Kubernetes operator for managing UniFi network configurations declaratively through Kubernetes Custom Resources.
## Introduction
This Helm chart deploys the UniFi Network Operator on a Kubernetes cluster. The operator enables you to manage UniFi network infrastructure (firewall zones, groups, policies, networks, and port forwards) using Kubernetes resources.
## Prerequisites
- Kubernetes 1.19+
- Helm 3.0+
- Access to a UniFi Network Controller
- UniFi controller credentials (URL, username, password)
## Installing the Chart
To install the chart with the release name `unifi-network-operator`:
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://unifi.example.com:8443" \
--set unifi.username="admin" \
--set unifi.password="your-password" \
--set unifi.site="default"
```
## Uninstalling the Chart
To uninstall/delete the `unifi-network-operator` deployment:
```bash
helm uninstall unifi-network-operator -n unifi-network-operator-system
```
This command removes all the Kubernetes components associated with the chart. Note that CRDs are not deleted by default to prevent data loss.
## Configuration
The following table lists the configurable parameters of the UniFi Network Operator chart and their default values.
### General Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `replicaCount` | Number of operator replicas | `1` |
| `image.repository` | Operator image repository | `gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller` |
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
| `image.tag` | Image tag (overrides appVersion) | `latest` |
| `imagePullSecrets` | Image pull secrets | `[]` |
| `nameOverride` | Override chart name | `""` |
| `fullnameOverride` | Override full chart name | `""` |
### Service Account Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `serviceAccount.create` | Create service account | `true` |
| `serviceAccount.automount` | Auto-mount service account token | `true` |
| `serviceAccount.annotations` | Service account annotations | `{}` |
| `serviceAccount.name` | Service account name | `""` |
### Security Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `podSecurityContext.runAsNonRoot` | Run as non-root user | `true` |
| `podSecurityContext.seccompProfile.type` | Seccomp profile type | `RuntimeDefault` |
| `securityContext.allowPrivilegeEscalation` | Allow privilege escalation | `false` |
| `securityContext.capabilities.drop` | Dropped capabilities | `["ALL"]` |
### Resource Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `resources.limits.cpu` | CPU limit | `500m` |
| `resources.limits.memory` | Memory limit | `128Mi` |
| `resources.requests.cpu` | CPU request | `10m` |
| `resources.requests.memory` | Memory request | `64Mi` |
### UniFi Controller Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `unifi.url` | UniFi controller URL | `""` (required) |
| `unifi.site` | UniFi site ID | `"default"` |
| `unifi.username` | UniFi username | `"admin"` |
| `unifi.password` | UniFi password | `""` (required) |
| `unifi.existingSecret` | Use existing secret for credentials | `""` |
| `unifi.existingSecretKeys.url` | Key for URL in existing secret | `UNIFI_URL` |
| `unifi.existingSecretKeys.site` | Key for site in existing secret | `UNIFI_SITE` |
| `unifi.existingSecretKeys.username` | Key for username in existing secret | `UNIFI_USERNAME` |
| `unifi.existingSecretKeys.password` | Key for password in existing secret | `UNIFI_PASSWORD` |
### Operator Configuration Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `config.create` | Create ConfigMap for operator config | `true` |
| `config.defaultNamespace` | Default namespace for resources | `"default"` |
| `config.fullSyncZone` | Full sync zone name | `""` |
| `config.fullSyncNetwork` | Full sync network name | `""` |
| `config.kubernetesUnifiZone` | Kubernetes UniFi zone name | `""` |
| `config.existingConfigMap` | Use existing ConfigMap | `""` |
### RBAC Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `rbac.create` | Create RBAC resources | `true` |
### CRD Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `crds.install` | Install CRDs | `true` |
| `crds.keep` | Keep CRDs on uninstall | `true` |
### Service Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `service.enabled` | Enable metrics service | `true` |
| `service.type` | Service type | `ClusterIP` |
| `service.port` | Service port | `8443` |
| `service.annotations` | Service annotations | `{}` |
### Metrics Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `metrics.serviceMonitor.enabled` | Enable Prometheus ServiceMonitor | `false` |
| `metrics.serviceMonitor.additionalLabels` | Additional labels for ServiceMonitor | `{}` |
| `metrics.serviceMonitor.interval` | Scrape interval | `30s` |
| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout | `10s` |
### Other Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| `leaderElection.enabled` | Enable leader election | `true` |
| `nodeSelector` | Node selector | `{}` |
| `tolerations` | Tolerations | `[]` |
| `affinity` | Affinity rules | `{}` |
| `podAnnotations` | Pod annotations | `{"kubectl.kubernetes.io/default-container": "manager"}` |
| `podLabels` | Pod labels | `{"control-plane": "controller-manager"}` |
## Using an Existing Secret
If you prefer to manage the UniFi credentials separately, you can create a secret manually and reference it:
```bash
kubectl create secret generic my-unifi-secret \
--from-literal=UNIFI_URL="https://unifi.example.com:8443" \
--from-literal=UNIFI_SITE="default" \
--from-literal=UNIFI_USERNAME="admin" \
--from-literal=UNIFI_PASSWORD="your-password" \
-n unifi-network-operator-system
```
Then install the chart with:
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
--namespace unifi-network-operator-system \
--create-namespace \
--set unifi.existingSecret="my-unifi-secret"
```
## Examples
### Basic Installation
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://192.168.1.1:8443" \
--set unifi.password="mypassword"
```
### Installation with Custom Configuration
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
--set unifi.url="https://unifi.example.com:8443" \
--set unifi.username="operator" \
--set unifi.password="secure-password" \
--set unifi.site="main" \
--set config.defaultNamespace="production" \
--set config.fullSyncZone="gateway" \
--set config.fullSyncNetwork="core" \
--set resources.limits.memory="256Mi" \
--set metrics.serviceMonitor.enabled=true
```
### Using a Values File
Create a `my-values.yaml` file:
```yaml
unifi:
url: "https://unifi.example.com:8443"
username: "operator"
password: "my-secure-password"
site: "default"
config:
defaultNamespace: "default"
fullSyncZone: "gateway"
fullSyncNetwork: "core"
resources:
limits:
memory: 256Mi
requests:
memory: 128Mi
metrics:
serviceMonitor:
enabled: true
additionalLabels:
prometheus: kube-prometheus
```
Install with:
```bash
helm install unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system \
--create-namespace \
-f my-values.yaml
```
## Custom Resources
After installing the operator, you can create the following custom resources:
### FirewallZone
```yaml
apiVersion: unifi.engen.priv.no/v1beta1
kind: FirewallZone
metadata:
name: my-zone
spec:
zoneName: "my-zone"
```
### FirewallGroup
```yaml
apiVersion: unifi.engen.priv.no/v1beta1
kind: FirewallGroup
metadata:
name: web-servers
spec:
addresses:
- "10.0.1.100/32"
- "10.0.1.101/32"
ports:
- "80/tcp"
- "443/tcp"
```
### FirewallPolicy
```yaml
apiVersion: unifi.engen.priv.no/v1beta1
kind: FirewallPolicy
metadata:
name: allow-web
spec:
sourceZone: "wan"
destinationGroup: "web-servers"
```
### Networkconfiguration
```yaml
apiVersion: unifi.engen.priv.no/v1beta1
kind: Networkconfiguration
metadata:
name: vlan10
spec:
networkName: "VLAN10"
```
## Upgrading
To upgrade the operator to a new version:
```bash
helm upgrade unifi-network-operator ./helm/unifi-network-operator \
-n unifi-network-operator-system
```
## Troubleshooting
### Check Operator Logs
```bash
kubectl logs -n unifi-network-operator-system -l app.kubernetes.io/name=unifi-network-operator -f
```
### Check Operator Status
```bash
kubectl get deployment -n unifi-network-operator-system
kubectl get pods -n unifi-network-operator-system
```
### Verify CRDs are Installed
```bash
kubectl get crds | grep unifi.engen.priv.no
```
### Common Issues
1. **Authentication Failures**: Verify your UniFi credentials and URL are correct
2. **CRD Not Found**: Ensure CRDs are installed with `crds.install=true`
3. **Operator Not Starting**: Check resource limits and image pull secrets
## License
This chart is provided as-is under the same license as the UniFi Network Operator project.
## Support
For issues and questions, please refer to the project repository.

View File

@@ -0,0 +1,187 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.17.2
name: firewallgroups.unifi.engen.priv.no
spec:
group: unifi.engen.priv.no
names:
kind: FirewallGroup
listKind: FirewallGroupList
plural: firewallgroups
singular: firewallgroup
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: FirewallGroup is the Schema for the firewallgroups 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:
auto_created_from:
properties:
name:
type: string
namespace:
type: string
type: object
autoIncludeSelector:
description: AutoIncludeSelector defines which services to extract
addresses from
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
type: object
x-kubernetes-map-type: atomic
id:
description: |-
Foo is an example field of FirewallGroup. Edit firewallgroup_types.go to remove/update
Description is a human-readable explanation for the object
type: string
manual_services:
items:
properties:
name:
type: string
namespace:
type: string
type: object
type: array
manualAddresses:
description: ManualAddresses is a list of manual IPs or CIDRs (IPv4
or IPv6)
items:
type: string
type: array
manualPorts:
items:
type: string
type: array
matchServicesInAllNamespaces:
type: boolean
name:
type: string
type: object
status:
description: FirewallGroupStatus defines the observed state of FirewallGroup.
properties:
lastSyncTime:
description: LastSyncTime is the last time the object was synced
format: date-time
type: string
resolvedIPV4Addresses:
items:
type: string
type: array
resolvedIPV6Addresses:
items:
type: string
type: array
resolvedTCPorts:
items:
type: string
type: array
resolvedUDPorts:
items:
type: string
type: array
resources_managed:
properties:
ipv4_object:
properties:
id:
type: string
name:
type: string
type: object
ipv6_object:
properties:
id:
type: string
name:
type: string
type: object
tcp_ports_object:
properties:
id:
type: string
name:
type: string
type: object
udp_ports_object:
properties:
id:
type: string
name:
type: string
type: object
type: object
syncedWithUnifi:
description: SyncedWithUnifi indicates whether the addresses are successfully
pushed
type: boolean
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@@ -0,0 +1,138 @@
---
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: {}

View File

@@ -0,0 +1,75 @@
---
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: {}

View File

@@ -0,0 +1,117 @@
---
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: {}

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

@@ -0,0 +1,49 @@
Thank you for installing {{ .Chart.Name }}!
Your release is named {{ .Release.Name }}.
The UniFi Network Operator has been deployed to namespace: {{ .Release.Namespace }}
To learn more about the release, try:
$ helm status {{ .Release.Name }} -n {{ .Release.Namespace }}
$ helm get all {{ .Release.Name }} -n {{ .Release.Namespace }}
{{- if not .Values.unifi.existingSecret }}
IMPORTANT: Make sure to configure your UniFi controller credentials properly.
The operator requires the following environment variables to be set:
- UNIFI_URL: {{ .Values.unifi.url }}
- UNIFI_SITE: {{ .Values.unifi.site }}
- UNIFI_USER: {{ .Values.unifi.username }}
- UNIFI_PASSWORD: [CONFIGURED]
{{- end }}
{{- if .Values.config.create }}
Operator configuration has been created with:
{{- if .Values.config.defaultNamespace }}
- Default Namespace: {{ .Values.config.defaultNamespace }}
{{- end }}
{{- if .Values.config.fullSyncZone }}
- Full Sync Zone: {{ .Values.config.fullSyncZone }}
{{- end }}
{{- if .Values.config.fullSyncNetwork }}
- Full Sync Network: {{ .Values.config.fullSyncNetwork }}
{{- end }}
{{- if .Values.config.kubernetesUnifiZone }}
- Kubernetes UniFi Zone: {{ .Values.config.kubernetesUnifiZone }}
{{- end }}
{{- end }}
To get the operator logs:
$ kubectl logs -n {{ .Release.Namespace }} -l {{ include "unifi-network-operator.selectorLabels" . | replace "\n" "," }} -f
Next steps:
1. Create FirewallZone resources to manage UniFi firewall zones
2. Create FirewallGroup resources to group IP addresses and ports
3. Create FirewallPolicy resources to define firewall rules
4. Create Networkconfiguration resources to manage network settings
5. Annotate Services for port forwarding
For more information, visit: {{ .Chart.Home }}

View File

@@ -0,0 +1,83 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "unifi-network-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "unifi-network-operator.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "unifi-network-operator.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "unifi-network-operator.labels" -}}
helm.sh/chart: {{ include "unifi-network-operator.chart" . }}
{{ include "unifi-network-operator.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "unifi-network-operator.selectorLabels" -}}
app.kubernetes.io/name: {{ include "unifi-network-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
control-plane: controller-manager
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "unifi-network-operator.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "unifi-network-operator.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Create the name of the secret to use
*/}}
{{- define "unifi-network-operator.secretName" -}}
{{- if .Values.unifi.existingSecret }}
{{- .Values.unifi.existingSecret }}
{{- else }}
{{- include "unifi-network-operator.fullname" . }}-unifi
{{- end }}
{{- end }}
{{/*
Create the name of the configmap to use
*/}}
{{- define "unifi-network-operator.configMapName" -}}
{{- if .Values.config.existingConfigMap }}
{{- .Values.config.existingConfigMap }}
{{- else }}
{{- include "unifi-network-operator.fullname" . }}-config
{{- end }}
{{- end }}

View File

@@ -0,0 +1,56 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "unifi-network-operator.fullname" . }}-manager-role
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
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
{{- end }}

View File

@@ -0,0 +1,16 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "unifi-network-operator.fullname" . }}-manager-rolebinding
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "unifi-network-operator.fullname" . }}-manager-role
subjects:
- kind: ServiceAccount
name: {{ include "unifi-network-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -0,0 +1,22 @@
{{- if .Values.config.create -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "unifi-network-operator.configMapName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
data:
{{- if .Values.config.defaultNamespace }}
defaultNamespace: {{ .Values.config.defaultNamespace | quote }}
{{- end }}
{{- if .Values.config.fullSyncZone }}
fullSyncZone: {{ .Values.config.fullSyncZone | quote }}
{{- end }}
{{- if .Values.config.fullSyncNetwork }}
fullSyncNetwork: {{ .Values.config.fullSyncNetwork | quote }}
{{- end }}
{{- if .Values.config.kubernetesUnifiZone }}
kubernetesUnifiZone: {{ .Values.config.kubernetesUnifiZone | quote }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,82 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "unifi-network-operator.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "unifi-network-operator.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "unifi-network-operator.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: manager
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
{{- if .Values.leaderElection.enabled }}
- --leader-elect
{{- end }}
- --health-probe-bind-address=:8081
env:
- name: UNIFI_URL
valueFrom:
secretKeyRef:
name: {{ include "unifi-network-operator.secretName" . }}
key: {{ .Values.unifi.existingSecretKeys.url }}
- name: UNIFI_SITE
valueFrom:
secretKeyRef:
name: {{ include "unifi-network-operator.secretName" . }}
key: {{ .Values.unifi.existingSecretKeys.site }}
- name: UNIFI_USER
valueFrom:
secretKeyRef:
name: {{ include "unifi-network-operator.secretName" . }}
key: {{ .Values.unifi.existingSecretKeys.username }}
- name: UNIFI_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "unifi-network-operator.secretName" . }}
key: {{ .Values.unifi.existingSecretKeys.password }}
securityContext:
{{- toYaml .Values.securityContext | nindent 10 }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 10 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 10 }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
terminationGracePeriodSeconds: 10

View File

@@ -0,0 +1,41 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "unifi-network-operator.fullname" . }}-leader-election-role
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
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
{{- end }}

View File

@@ -0,0 +1,17 @@
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "unifi-network-operator.fullname" . }}-leader-election-rolebinding
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "unifi-network-operator.fullname" . }}-leader-election-role
subjects:
- kind: ServiceAccount
name: {{ include "unifi-network-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

View File

@@ -0,0 +1,15 @@
{{- if not .Values.unifi.existingSecret -}}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "unifi-network-operator.fullname" . }}-unifi
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
type: Opaque
stringData:
{{ .Values.unifi.existingSecretKeys.url }}: {{ .Values.unifi.url | required "unifi.url is required when not using an existing secret" | quote }}
{{ .Values.unifi.existingSecretKeys.site }}: {{ .Values.unifi.site | quote }}
{{ .Values.unifi.existingSecretKeys.username }}: {{ .Values.unifi.username | quote }}
{{ .Values.unifi.existingSecretKeys.password }}: {{ .Values.unifi.password | required "unifi.password is required when not using an existing secret" | quote }}
{{- end }}

View File

@@ -0,0 +1,22 @@
{{- if .Values.service.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "unifi-network-operator.fullname" . }}-metrics
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
{{- with .Values.service.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
ports:
- name: https
port: {{ .Values.service.port }}
targetPort: 8443
protocol: TCP
selector:
{{- include "unifi-network-operator.selectorLabels" . | nindent 4 }}
{{- end }}

View File

@@ -0,0 +1,14 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "unifi-network-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
{{- end }}

View File

@@ -0,0 +1,24 @@
{{- if .Values.metrics.serviceMonitor.enabled -}}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "unifi-network-operator.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "unifi-network-operator.labels" . | nindent 4 }}
{{- with .Values.metrics.serviceMonitor.additionalLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
endpoints:
- interval: {{ .Values.metrics.serviceMonitor.interval }}
path: /metrics
port: https
scheme: https
scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }}
tlsConfig:
insecureSkipVerify: true
selector:
matchLabels:
{{- include "unifi-network-operator.selectorLabels" . | nindent 6 }}
{{- end }}

View File

@@ -0,0 +1,159 @@
# Default values for unifi-network-operator
# -- Number of replicas for the operator deployment
replicaCount: 1
image:
# -- Container image repository
repository: gitea.engen.priv.no/klauvsteinen/unifi-network-operator-controller
# -- Image pull policy
pullPolicy: IfNotPresent
# -- Overrides the image tag whose default is the chart appVersion
tag: "latest"
# -- Image pull secrets for private registries
imagePullSecrets: []
# -- Override the name of the chart
nameOverride: ""
# -- Override the full name of the chart
fullnameOverride: ""
serviceAccount:
# -- Specifies whether a service account should be created
create: true
# -- Automatically mount a ServiceAccount's API credentials
automount: true
# -- Annotations to add to the service account
annotations: {}
# -- The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# -- Annotations to add to the pod
podAnnotations:
kubectl.kubernetes.io/default-container: manager
# -- Labels to add to the pod
podLabels:
control-plane: controller-manager
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
service:
# -- Enable metrics service
enabled: true
# -- Service type
type: ClusterIP
# -- Metrics port
port: 8443
# -- Annotations to add to the service
annotations: {}
resources:
limits:
# -- CPU limit
cpu: 500m
# -- Memory limit
memory: 128Mi
requests:
# -- CPU request
cpu: 10m
# -- Memory request
memory: 64Mi
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
# -- Node selector for pod assignment
nodeSelector: {}
# -- Tolerations for pod assignment
tolerations: []
# -- Affinity for pod assignment
affinity: {}
# Leader election configuration
leaderElection:
# -- Enable leader election for high availability
enabled: true
# UniFi controller configuration
unifi:
# -- UniFi controller URL (e.g., https://unifi.example.com:8443)
url: ""
# -- UniFi site ID (e.g., default)
site: "default"
# -- UniFi username
username: "admin"
# -- UniFi password (leave empty to use existing secret)
password: ""
# -- Use existing secret for UniFi credentials
# If set, the chart will not create a secret
existingSecret: ""
# -- Keys in the existing secret for UniFi credentials
existingSecretKeys:
url: UNIFI_URL
site: UNIFI_SITE
username: UNIFI_USERNAME
password: UNIFI_PASSWORD
# Operator configuration
config:
# -- Create a ConfigMap for operator configuration
create: true
# -- Default namespace for resources
defaultNamespace: "default"
# -- Full sync zone name (zone for bidirectional sync)
fullSyncZone: ""
# -- Full sync network name (network for bidirectional sync)
fullSyncNetwork: ""
# -- Kubernetes UniFi zone name
kubernetesUnifiZone: ""
# -- Use existing ConfigMap for operator configuration
existingConfigMap: ""
# CRD configuration
crds:
# -- Install CRDs as part of the Helm chart
install: true
# -- Keep CRDs on chart uninstall
keep: true
# RBAC configuration
rbac:
# -- Create RBAC resources
create: true
# Metrics configuration
metrics:
# -- Enable Prometheus ServiceMonitor
serviceMonitor:
enabled: false
# -- Additional labels for the ServiceMonitor
additionalLabels: {}
# -- Scrape interval
interval: 30s
# -- Scrape timeout
scrapeTimeout: 10s

View File

@@ -38,10 +38,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
// "sigs.k8s.io/controller-runtime/pkg/source"
goUnifi "github.com/vegardengen/go-unifi/unifi"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi"
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"
)
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")
return reconcile.Result{}, err
}
ipv4_name := "k8s-" + firewallGroup.Spec.Name + "-ipv4"
ipv6_name := "k8s-" + firewallGroup.Spec.Name + "-ipv6"
tcpports_name := "k8s-" + firewallGroup.Spec.Name + "-tcpports"
udpports_name := "k8s-" + firewallGroup.Spec.Name + "-udpports"
ipv4_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-ipv4"
ipv6_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-ipv6"
tcpports_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-tcpports"
udpports_name := "k8s-" + firewallGroup.Namespace + "/" + firewallGroup.Name + "-udpports"
ipv4_done := false
ipv6_done := false
tcpports_done := false
@@ -377,7 +377,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"127.0.0.1"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -417,7 +417,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"::1"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -457,7 +457,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"0"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -497,7 +497,7 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg,"invalid character") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"127.0.0.1"}
firewall_group.Name = firewall_group.Name + "-deleted"

View File

@@ -27,7 +27,7 @@ import (
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() {

View File

@@ -33,10 +33,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
goUnifi "github.com/vegardengen/go-unifi/unifi"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi"
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"
)
// FirewallPolicyReconciler reconciles a FirewallPolicy object
@@ -125,70 +125,72 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
log.Info("Running finalizer logic for FirewallPolicy", "name", firewallPolicy.Name)
if len(firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies) > 0 {
for i, UnifiFirewallPolicy := range firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies {
log.Info(fmt.Sprintf("From: %s to: %s TcpIpv4: %s UdpIpv4: %s TcpIpv6: %s UdpIpv6: %s", UnifiFirewallPolicy.From, UnifiFirewallPolicy.To, UnifiFirewallPolicy.TcpIpv4ID, UnifiFirewallPolicy.UdpIpv4ID, UnifiFirewallPolicy.TcpIpv6ID, UnifiFirewallPolicy.UdpIpv6ID))
if len(UnifiFirewallPolicy.TcpIpv4ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.TcpIpv4ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].TcpIpv4ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
if firewallPolicy.Status.ResourcesManaged != nil {
if len(firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies) > 0 {
for i, UnifiFirewallPolicy := range firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies {
log.Info(fmt.Sprintf("From: %s to: %s TcpIpv4: %s UdpIpv4: %s TcpIpv6: %s UdpIpv6: %s", UnifiFirewallPolicy.From, UnifiFirewallPolicy.To, UnifiFirewallPolicy.TcpIpv4ID, UnifiFirewallPolicy.UdpIpv4ID, UnifiFirewallPolicy.TcpIpv6ID, UnifiFirewallPolicy.UdpIpv6ID))
if len(UnifiFirewallPolicy.TcpIpv4ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.TcpIpv4ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].TcpIpv4ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
}
if len(UnifiFirewallPolicy.UdpIpv4ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.UdpIpv4ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].UdpIpv4ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
if len(UnifiFirewallPolicy.UdpIpv4ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.UdpIpv4ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].UdpIpv4ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
}
if len(UnifiFirewallPolicy.TcpIpv6ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.TcpIpv6ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].TcpIpv6ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
if len(UnifiFirewallPolicy.TcpIpv6ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.TcpIpv6ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].TcpIpv6ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
}
if len(UnifiFirewallPolicy.UdpIpv6ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.UdpIpv6ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].UdpIpv6ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
if len(UnifiFirewallPolicy.UdpIpv6ID) > 0 {
err := r.UnifiClient.Client.DeleteFirewallPolicy(context.Background(), r.UnifiClient.SiteID, UnifiFirewallPolicy.UdpIpv6ID)
if err != nil && !strings.Contains(err.Error(), "not found") {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
} else {
firewallPolicy.Status.ResourcesManaged.UnifiFirewallPolicies[i].UdpIpv6ID = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
}
}
}
if len(firewallPolicy.Status.ResourcesManaged.FirewallGroups) > 0 {
for i, firewallGroup := range firewallPolicy.Status.ResourcesManaged.FirewallGroups {
var firewallGroupCRD unifiv1beta1.FirewallGroup
if firewallGroup.Name != "" {
if err := r.Get(ctx, types.NamespacedName{Name: firewallGroup.Name, Namespace: firewallGroup.Namespace}, &firewallGroupCRD); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
if err := r.Delete(ctx, &firewallGroupCRD); err != nil {
log.Error(err, "Could not delete firewall group")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
firewallPolicy.Status.ResourcesManaged.FirewallGroups[i].Name = ""
firewallPolicy.Status.ResourcesManaged.FirewallGroups[i].Namespace = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
if len(firewallPolicy.Status.ResourcesManaged.FirewallGroups) > 0 {
for i, firewallGroup := range firewallPolicy.Status.ResourcesManaged.FirewallGroups {
var firewallGroupCRD unifiv1beta1.FirewallGroup
if firewallGroup.Name != "" {
if err := r.Get(ctx, types.NamespacedName{Name: firewallGroup.Name, Namespace: firewallGroup.Namespace}, &firewallGroupCRD); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
if err := r.Delete(ctx, &firewallGroupCRD); err != nil {
log.Error(err, "Could not delete firewall group")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
firewallPolicy.Status.ResourcesManaged.FirewallGroups[i].Name = ""
firewallPolicy.Status.ResourcesManaged.FirewallGroups[i].Namespace = ""
if err := r.Status().Update(ctx, &firewallPolicy); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
}
@@ -285,14 +287,14 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
// This will be used when running through all firewall groups and servics known, to see if a rule should be added.
for _, dest_group := range firewallPolicy.Spec.Destination.FirewallGroups {
namespace := defaultNs
namespace := firewallPolicy.Namespace
if len(dest_group.Namespace) > 0 {
namespace = dest_group.Namespace
}
destination_groups[namespace+"/"+dest_group.Name] = struct{}{}
}
for _, dest_service := range firewallPolicy.Spec.Destination.Services {
namespace := defaultNs
namespace := firewallPolicy.Namespace
if len(dest_service.Namespace) > 0 {
namespace = dest_service.Namespace
}
@@ -310,7 +312,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
// Run through all firewall groups. Add them to the myFirewallGroups list if they either have an annotations or is specified in the resource.
for _, firewallGroup := range firewallGroupCRDs.Items {
if val, found := firewallGroup.Annotations["unifi.engen.priv.no/firewall-policy"]; found && ((strings.Contains(val, "/") && val == firewallPolicy.Namespace+"/"+firewallPolicy.Name) || (val == firewallPolicy.Name && firewallPolicy.Namespace == defaultNs)) {
if val, found := firewallGroup.Annotations["unifi.engen.priv.no/firewall-policy"]; found && ((strings.Contains(val, "/") && val == firewallPolicy.Namespace+"/"+firewallPolicy.Name) || (val == firewallPolicy.Name && firewallPolicy.Namespace == firewallGroup.Namespace)) {
myFirewallGroups = append(myFirewallGroups, firewallGroup)
} else if _, found := destination_groups[firewallGroup.Namespace+"/"+firewallGroup.Name]; found {
myFirewallGroups = append(myFirewallGroups, firewallGroup)
@@ -340,7 +342,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
skipService = true
}
}
if val, found := service.Annotations["unifi.engen.priv.no/firewall-policy"]; found && ((strings.Contains(val, "/") && val == firewallPolicy.Namespace+"/"+firewallPolicy.Name) || (val == firewallPolicy.Name && firewallPolicy.Namespace == defaultNs)) && !skipService {
if val, found := service.Annotations["unifi.engen.priv.no/firewall-policy"]; found && ((strings.Contains(val, "/") && val == firewallPolicy.Namespace+"/"+firewallPolicy.Name) || (val == firewallPolicy.Name && firewallPolicy.Namespace == service.Namespace)) && !skipService {
myServices = append(myServices, service)
} else if _, found := destination_services[service.Namespace+"/"+service.Name]; found && !skipService {
myServices = append(myServices, service)
@@ -468,7 +470,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
if len(firewallGroup.Status.ResolvedIPV4Addresses) > 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 {
log.Info(fmt.Sprintf("Creating ipv4 tcp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -503,7 +505,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
}
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 {
log.Info(fmt.Sprintf("Creating ipv4 udp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -541,7 +543,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
if len(firewallGroup.Status.ResolvedIPV6Addresses) > 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 {
log.Info(fmt.Sprintf("Creating ipv6 tcp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -577,7 +579,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
}
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 {
log.Info(fmt.Sprintf("Creating ipv6 udp firewallpolicy for %s to %s: %s", zoneCRDs.Items[zoneIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -640,7 +642,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
if len(firewallGroup.Status.ResolvedIPV4Addresses) > 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 {
log.Info(fmt.Sprintf("Creating ipv4 tcp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -677,7 +679,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
}
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 {
log.Info(fmt.Sprintf("Creating ipv4 udp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -716,7 +718,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
if len(firewallGroup.Status.ResolvedIPV6Addresses) > 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 {
log.Info(fmt.Sprintf("Creating ipv6 tcp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()
@@ -753,7 +755,7 @@ func (r *FirewallPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Reque
}
}
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 {
log.Info(fmt.Sprintf("Creating ipv6 udp firewallpolicy for %s to %s: %s", networkCRDs.Items[networkIndex].Name, firewallGroup.Name, policyname))
unifiFirewallPolicy := fillDefaultPolicy()

View File

@@ -27,7 +27,7 @@ import (
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() {

View File

@@ -28,9 +28,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/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"
)
// FirewallZoneReconciler reconciles a FirewallZone object

View File

@@ -27,7 +27,7 @@ import (
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() {

View File

@@ -28,9 +28,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
unifiv1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi"
unifiv1 "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"
)
// NetworkconfigurationReconciler reconciles a Networkconfiguration object

View File

@@ -27,7 +27,7 @@ import (
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() {

View File

@@ -18,10 +18,10 @@ import (
// "sigs.k8s.io/controller-runtime/pkg/reconcile"
// "sigs.k8s.io/controller-runtime/pkg/source"
goUnifi "github.com/vegardengen/go-unifi/unifi"
// unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1"
"github.com/vegardengen/unifi-network-operator/internal/config"
"github.com/vegardengen/unifi-network-operator/internal/unifi"
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 {

View File

@@ -27,7 +27,7 @@ import (
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("PortForward Controller", func() {

View File

@@ -32,7 +32,7 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
"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
)

View File

@@ -13,7 +13,7 @@ import (
"strings"
"sync"
"github.com/vegardengen/go-unifi/unifi"
"gitea.engen.priv.no/klauvsteinen/go-unifi/unifi"
)
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: ""