Compare commits

..

164 Commits

Author SHA1 Message Date
vegard ea68bed9c2 Add helm
Build project / build (push) Successful in 4m43s
2025-10-21 07:23:07 +02:00
vegard 32a595d160 Merge pull request 'Handle services in same namespace if namespace is not specified' (#34) from feature/properly-handle-namespaced-services into main
Publish / build (push) Successful in 2m0s
Reviewed-on: #34
2025-06-28 23:14:01 +00:00
vegard 834f52c015 Handle services in same namespace if namespace is not specified
Build project / build (push) Successful in 1m42s
2025-06-29 01:12:26 +02:00
vegard 9d43b517e6 Merge pull request 'Properly check for firewallGroup in same namespace' (#33) from feature/properly-handle-firewallgroups-in-same-namespace into main
Publish / build (push) Successful in 2m27s
Reviewed-on: #33
2025-06-28 23:07:05 +00:00
vegard 2b38f08a1a Merge pull request 'feature/cleanly-delete-empty-resources' (#32) from feature/cleanly-delete-empty-resources into main
Publish / build (push) Has been cancelled
Reviewed-on: #32
2025-06-28 22:59:42 +00:00
vegard 3a63034e26 Properly check for firewallGroup in same namespace
Build project / build (push) Successful in 1m54s
Publish / build (push) Successful in 2m0s
2025-06-29 00:58:57 +02:00
vegard 37d8060995 Check for nil ResourcesManaged
Build project / build (push) Successful in 2m0s
Publish / build (push) Successful in 2m4s
2025-06-29 00:44:49 +02:00
vegard 8623d6cbc0 debug
Build project / build (push) Successful in 1m52s
Publish / build (push) Successful in 2m2s
2025-06-29 00:24:00 +02:00
vegard 61606e8a7e debug 2025-06-29 00:23:26 +02:00
vegard 44d89a5a50 Check for nil instead of length
Build project / build (push) Failing after 1m7s
2025-06-29 00:17:44 +02:00
vegard 19f24add0a Check for Status field before checking for managed resources
Build project / build (push) Failing after 1m9s
Publish / build (push) Failing after 1m20s
2025-06-29 00:11:49 +02:00
vegard 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
Publish / build (push) Successful in 2m16s
Reviewed-on: #31
2025-06-28 21:56:08 +00:00
vegard 990140ee1c Check for firewallGroup in same namespace if namespace is not defined
Build project / build (push) Successful in 1m51s
2025-06-28 23:53:51 +02:00
vegard 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
Publish / build (push) Successful in 2m1s
Reviewed-on: #30
2025-06-28 16:38:11 +00:00
vegard 938d53fa8f Fix namespace matching for firewallgroups in firewallpolicies
Publish / build (push) Successful in 2m5s
Build project / build (push) Successful in 1m55s
2025-06-28 18:33:54 +02:00
vegard 768c61020e Merge pull request 'feature/add-namespace-to-firewallgroup-and-firewallpolicy-resources' (#29) from feature/add-namespace-to-firewallgroup-and-firewallpolicy-resources into main
Publish / build (push) Successful in 1m58s
Reviewed-on: #29
2025-06-27 15:48:14 +00:00
vegard 8d70a78a50 fix
Build project / build (push) Successful in 1m47s
Publish / build (push) Successful in 1m59s
2025-06-27 17:01:55 +02:00
vegard 5885daac55 Fix
Build project / build (push) Failing after 1m9s
Publish / build (push) Failing after 1m19s
2025-06-27 16:53:44 +02:00
vegard 440dc04e5b Add namespace to some names
Build project / build (push) Failing after 1m10s
Publish / build (push) Failing after 1m21s
2025-06-27 16:51:05 +02:00
vegard 22c8df6833 Add namespace to name of firewallgroups 2025-06-27 16:46:45 +02:00
vegard 35d95d107c Merge pull request 'Use pre-built image' (#28) from feature/use-prebuilt-image into main
Publish / build (push) Has been cancelled
Reviewed-on: #28
2025-06-26 23:49:34 +00:00
vegard 4bb45b0128 Use pre-built image
Build project / build (push) Has been cancelled
Publish / build (push) Successful in 1m54s
2025-06-27 01:47:15 +02:00
vegard 9eefd08823 Merge pull request 'Add variables' (#27) from feature/fix-indentation into main
Build project / build (push) Has been cancelled
Publish / build (push) Has been cancelled
Reviewed-on: #27
2025-06-26 23:36:27 +00:00
vegard d53810b714 Add variables
Build project / build (push) Has been cancelled
2025-06-27 01:36:01 +02:00
vegard 33f1fd5eac Merge pull request 'Need docker on main build' (#26) from feature/fix-indentation into main
Publish / build (push) Failing after 2m21s
Reviewed-on: #26
2025-06-26 23:28:36 +00:00
vegard 9ae7d91365 Need docker on main build
Build project / build (push) Has been cancelled
2025-06-27 01:28:01 +02:00
vegard 6fe5fdf859 Merge pull request 'Fix indentation' (#25) from feature/fix-indentation into main
Publish / build (push) Failing after 1m9s
Reviewed-on: #25
2025-06-26 23:24:16 +00:00
vegard 37b5eb830a Fix indentation
Build project / build (push) Has been cancelled
2025-06-27 01:23:49 +02:00
vegard 1834527d43 feature/create-correct-manifests (#23)
Reviewed-on: #23
2025-06-26 23:19:55 +00:00
vegard b562c200ba Merge pull request 'split up regex' (#22) from feature/build-alpha-and-beta into main
Publish / build (push) Successful in 2m53s
Reviewed-on: #22
2025-06-26 22:19:58 +00:00
vegard 2485365728 split up regex
Build project / build (push) Has been cancelled
Publish / build (push) Successful in 3m22s
2025-06-27 00:18:05 +02:00
vegard efeaf521fd Merge pull request 'match alpha and beta tags' (#21) from feature/build-alpha-and-beta into main
Publish / build (push) Successful in 2m55s
Reviewed-on: #21
2025-06-26 22:08:57 +00:00
vegard 7ce8682ecb match alpha and beta tags
Build project / build (push) Successful in 2m14s
2025-06-27 00:07:04 +02:00
vegard 744e43c1f4 Merge pull request 'Add image url' (#20) from feature/update-image-labels into main
Publish / build (push) Successful in 3m22s
Reviewed-on: #20
2025-06-26 19:35:12 +00:00
vegard 8095723337 Add image url
Build project / build (push) Has been cancelled
2025-06-26 21:34:42 +02:00
vegard 9e7b6123c2 Merge pull request 'Override image labels' (#19) from feature/update-image-labels into main
Publish / build (push) Successful in 3m15s
Reviewed-on: #19
2025-06-26 19:14:46 +00:00
vegard 062b386f7f Override image labels
Build project / build (push) Successful in 1m54s
2025-06-26 21:14:23 +02:00
vegard aca35507ba Merge pull request 'Override image labels' (#18) from feature/update-image-labels into main
Publish / build (push) Failing after 1m35s
Reviewed-on: #18
2025-06-26 19:06:58 +00:00
vegard 4ede272b70 Override image labels
Build project / build (push) Successful in 1m58s
2025-06-26 21:06:25 +02:00
vegard 5e413a64e8 Merge pull request 'Add ko.yaml' (#17) from feature/update-image-labels into main
Publish / build (push) Successful in 3m22s
Reviewed-on: #17
2025-06-26 18:22:11 +00:00
vegard 1cfd5ef55c Add ko.yaml
Build project / build (push) Successful in 2m1s
2025-06-26 20:21:45 +02:00
vegard c89dad396b Merge pull request 'feature/generate-manifest' (#16) from feature/generate-manifest into main
Publish / build (push) Successful in 3m17s
Reviewed-on: #16
2025-06-25 18:30:29 +00:00
vegard cddda7098c generic in the path
Build project / build (push) Successful in 1m59s
2025-06-25 20:29:15 +02:00
vegard 9a186ad190 Add forgotten files
Build project / build (push) Successful in 1m58s
2025-06-25 17:52:28 +02:00
vegard 4ece12d18b Merge pull request 'Upload manifest' (#15) from feature/generate-manifest into main
Publish / build (push) Successful in 3m15s
Reviewed-on: #15
2025-06-25 15:48:20 +00:00
vegard 6d0df79c87 Upload manifest
Build project / build (push) Successful in 1m27s
2025-06-25 17:45:02 +02:00
vegard 445dd7830e Merge pull request 'Use image from gitea' (#14) from feature/use-image-from-gitea into main
Publish / build (push) Successful in 2m19s
Reviewed-on: #14
2025-06-25 15:26:34 +00:00
vegard a73aef4f9d Use image from gitea
Build project / build (push) Successful in 1m29s
2025-06-25 17:25:05 +02:00
vegard a99de02594 Merge pull request 'Fix variable reference' (#13) from feature/fix-variable into main
Publish / build (push) Successful in 3m2s
Reviewed-on: #13
2025-06-25 15:09:34 +00:00
vegard 893318ad53 Fix variable reference
Build project / build (push) Has been cancelled
2025-06-25 17:09:15 +02:00
vegard 201edb1b82 Merge pull request 'feature/fix' (#12) from feature/fix into main
Publish / build (push) Failing after 1m34s
Reviewed-on: #12
2025-06-25 15:01:09 +00:00
vegard b1c0a4ee11 :q:Merge branch 'feature/fix-push-workflow'
Build project / build (push) Successful in 1m28s
2025-06-25 16:59:39 +02:00
vegard 13677136a7 Fix variable reference
Build project / build (push) Has been cancelled
2025-06-25 16:57:02 +02:00
vegard cb296c3881 Fix variable reference 2025-06-25 16:57:02 +02:00
vegard 3c6b48803d fix secret names 2025-06-25 16:57:02 +02:00
vegard f71fa2af8e Add missing sign 2025-06-25 16:57:02 +02:00
vegard 1819ef2b60 Fix workflow 2025-06-25 16:57:02 +02:00
vegard 74d7ca84a5 Change package repo 2025-06-25 16:57:02 +02:00
vegard 0f7ffe3c85 cleanup 2025-06-25 16:57:02 +02:00
vegard 3020510c6f bare 2025-06-25 16:57:01 +02:00
vegard 475e226b69 fix 2025-06-25 16:57:01 +02:00
vegard a5521013b9 fix 2025-06-25 16:57:01 +02:00
vegard 4aa3436f28 fix 2025-06-25 16:57:01 +02:00
vegard 6e32555e9e fix 2025-06-25 16:57:01 +02:00
vegard 13c23863be fix 2025-06-25 16:57:01 +02:00
vegard 918b45c940 fix 2025-06-25 16:57:01 +02:00
vegard 3cb65a5a14 fix 2025-06-25 16:57:00 +02:00
vegard 4ae70ecf74 fix 2025-06-25 16:57:00 +02:00
vegard 3aa4d1a24a fix 2025-06-25 16:57:00 +02:00
vegard 1231bc50e5 fix 2025-06-25 16:57:00 +02:00
vegard e1847f4cf9 fix 2025-06-25 16:57:00 +02:00
vegard 55a206d509 fix 2025-06-25 16:57:00 +02:00
vegard 00179595e4 fix 2025-06-25 16:57:00 +02:00
vegard f09e008fb7 fix 2025-06-25 16:57:00 +02:00
vegard 14a8155dcf fix 2025-06-25 16:57:00 +02:00
vegard 93ef66f01d fix 2025-06-25 16:57:00 +02:00
vegard 80746321a9 fix 2025-06-25 16:57:00 +02:00
vegard 6423ef7d6e fix 2025-06-25 16:57:00 +02:00
vegard fdefd05608 fix 2025-06-25 16:57:00 +02:00
vegard 760fd3903f fix 2025-06-25 16:57:00 +02:00
vegard cda1c7ddff fix 2025-06-25 16:57:00 +02:00
vegard 1274fe610f fix 2025-06-25 16:57:00 +02:00
vegard f091ec148b Tag 2025-06-25 16:57:00 +02:00
vegard 66e1d854d3 Tag 2025-06-25 16:57:00 +02:00
vegard f43c1f3b63 fix tagging 2025-06-25 16:57:00 +02:00
vegard 0046157633 Fix variable reference (#10)
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
vegard 56a781a260 Merge pull request 'fix secret names' (#9) from feature/fix-push-workflow into main
Publish / build (push) Failing after 1m34s
Reviewed-on: #9
2025-06-25 14:35:35 +00:00
vegard 29fb9601fd fix secret names
Build project / build (push) Has been cancelled
2025-06-25 16:35:12 +02:00
vegard c34eea5e13 Merge pull request 'Add missing sign' (#8) from feature/fix-push-workflow into main
Publish / build (push) Failing after 1m34s
Reviewed-on: #8
2025-06-25 14:30:15 +00:00
vegard fe90ac7ea4 Add missing sign
Build project / build (push) Has been cancelled
2025-06-25 16:29:37 +02:00
vegard 31679a3f53 Merge pull request 'Fix workflow' (#7) from feature/fix-push-workflow into main
Publish / build (push) Has been cancelled
Reviewed-on: #7
2025-06-25 14:25:22 +00:00
vegard de38c76e24 Fix workflow
Build project / build (push) Has been cancelled
2025-06-25 16:25:03 +02:00
vegard 2a396ad981 Merge pull request 'Change package repo' (#6) from feature/push-to-gitea into main
Publish / build (push) Successful in 2m20s
Reviewed-on: #6
2025-06-25 14:21:03 +00:00
vegard f147ec8108 Change package repo
Build project / build (push) Has been cancelled
2025-06-25 16:20:35 +02:00
vegard b6a2b73eb8 Merge pull request 'cleanup' (#5) from feature/clean_some_files into main
Publish / build (push) Successful in 2m20s
Reviewed-on: #5
2025-06-25 13:41:23 +00:00
vegard 2304e33586 cleanup
Build project / build (push) Successful in 1m33s
2025-06-25 15:40:02 +02:00
vegard a40f1342fe Merge pull request 'feature/fix-publish-pipeline' (#4) from feature/fix-publish-pipeline into main
Publish / build (push) Successful in 2m29s
Reviewed-on: #4
2025-06-24 21:13:12 +00:00
vegard bd8d1f7c01 bare
Build project / build (push) Successful in 1m48s
Publish / build (push) Successful in 2m26s
2025-06-24 23:12:39 +02:00
vegard ac47c880ed fix
Build project / build (push) Has been cancelled
Publish / build (push) Successful in 2m21s
2025-06-24 12:01:15 +02:00
vegard 481091160b fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m6s
2025-06-24 11:58:06 +02:00
vegard 14e4fe1c46 fix
Publish / build (push) Has been cancelled
Build project / build (push) Has been cancelled
2025-06-24 11:57:31 +02:00
vegard 4901dfbad5 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m8s
2025-06-24 11:56:05 +02:00
vegard c454c78478 fix
Publish / build (push) Failing after 1m5s
Build project / build (push) Has been cancelled
2025-06-24 11:53:10 +02:00
vegard c30e27efc4 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m6s
2025-06-24 11:43:37 +02:00
vegard f2a943de3c fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 11:41:12 +02:00
vegard 720865c984 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 11:39:41 +02:00
vegard 913a24a613 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m6s
2025-06-24 11:33:40 +02:00
vegard 719ba853bc fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m8s
2025-06-24 11:31:09 +02:00
vegard 4e26fe02f5 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 3s
2025-06-24 11:29:54 +02:00
vegard cd61d5c82a fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 0s
2025-06-24 11:29:25 +02:00
vegard 6983253c9e fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 3s
2025-06-24 11:26:23 +02:00
vegard 1d7c7c864e fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1s
2025-06-24 11:25:03 +02:00
vegard 1a2def25bf fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1s
2025-06-24 11:21:51 +02:00
vegard 6c8503bf15 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m8s
2025-06-24 11:17:03 +02:00
vegard b9b86e0d5d fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 2m14s
2025-06-24 11:10:19 +02:00
vegard 2c9659409c fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 2m46s
2025-06-24 11:05:01 +02:00
vegard 20c4dda5ad fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 11:02:18 +02:00
vegard bb28850ca5 fix
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 34s
2025-06-24 10:58:27 +02:00
vegard f08c165628 fix
Publish / build (push) Failing after 1m13s
Build project / build (push) Has been cancelled
2025-06-24 10:54:43 +02:00
vegard 46e6217557 fix
Build project / build (push) Successful in 1m29s
Publish / build (push) Failing after 1s
2025-06-24 10:52:17 +02:00
vegard 36f337434d Tag
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m7s
2025-06-24 10:47:51 +02:00
vegard 3f14d82679 Tag
Build project / build (push) Has been cancelled
Publish / build (push) Failing after 1m11s
2025-06-24 10:42:24 +02:00
vegard 2817272082 Merge pull request 'fix tagging' (#3) from feature/fix-publish-pipeline into main
Publish / build (push) Failing after 1m7s
Reviewed-on: #3
2025-06-24 08:35:30 +00:00
vegard 1545f05d53 fix tagging
Build project / build (push) Has been cancelled
2025-06-24 10:35:05 +02:00
vegard 47116c70b5 Merge pull request 'ko build --local on main' (#2) from feature/kobuild-on-main into main
Publish / build (push) Successful in 2m24s
Reviewed-on: #2
2025-06-24 08:24:32 +00:00
vegard 0eb5b5c2eb ko build --local on main
Build project / build (push) Successful in 1m27s
2025-06-24 10:23:55 +02:00
vegard 7e6573deb4 Merge pull request 'ko build on main' (#1) from feature/kobuild-on-main into main
Publish / build (push) Successful in 2m19s
Reviewed-on: #1
2025-06-24 08:15:36 +00:00
vegard e22a4c4992 ko build on main
Build project / build (push) Successful in 1m27s
2025-06-24 10:14:52 +02:00
vegard 401f4a7cf7 build on non-main
Build project / build (push) Successful in 1m30s
2025-06-24 10:10:56 +02:00
vegard 68e8782da4 Publish
Publish / build (push) Successful in 2m20s
2025-06-24 10:03:25 +02:00
vegard e95a4c13e6 Publish
Publish / build (push) Failing after 1m7s
2025-06-24 10:00:49 +02:00
vegard d82d7d2902 Build only on branch push 2025-06-24 09:59:45 +02:00
vegard 3091c89fa8 Build only on branch push 2025-06-24 09:57:32 +02:00
vegard 853fca1635 Build only on branch push 2025-06-24 09:57:01 +02:00
vegard 07208979e3 Build only on branch push 2025-06-24 09:56:05 +02:00
vegard c86196aa88 ko
Build project / build (push) Successful in 1m26s
Publish / build (push) Failing after 1m9s
2025-06-24 09:48:43 +02:00
vegard a35bc7220d pipelines
Build project / build (push) Successful in 1m29s
2025-06-24 09:44:19 +02:00
vegard 446fb89d00 Change workflow 2025-06-24 09:40:44 +02:00
vegard 4bf3adaf87 test
Build & Push Linode Webhook / build (push) Successful in 1m30s
2025-06-24 01:48:34 +02:00
vegard d7f2d8031e fix
Build & Push Linode Webhook / build (push) Successful in 1m31s
2025-06-24 01:47:34 +02:00
vegard 604cc20505 fix
Build & Push Linode Webhook / build (push) Successful in 1m32s
2025-06-24 01:45:10 +02:00
vegard 572521747f fix
Build & Push Linode Webhook / build (push) Failing after 7s
2025-06-24 01:43:34 +02:00
vegard acea7fd46e fix 2025-06-24 01:42:50 +02:00
vegard 634021854d fix
Build & Push Linode Webhook / build (push) Failing after 33s
2025-06-24 01:34:02 +02:00
vegard 1e0a51f83b fix
Build & Push Linode Webhook / build (push) Failing after 6s
2025-06-24 01:33:19 +02:00
vegard cab7bc2f5a fix
Build & Push Linode Webhook / build (push) Failing after 2s
2025-06-24 01:31:49 +02:00
vegard cef43b9c3e fix
Build & Push Linode Webhook / build (push) Failing after 25s
2025-06-24 01:29:31 +02:00
vegard 019a33a69a fix
Build & Push Linode Webhook / build (push) Failing after 2s
2025-06-24 01:27:30 +02:00
vegard c2ff504510 fix
Build & Push Linode Webhook / build (push) Failing after 3s
2025-06-24 01:26:43 +02:00
vegard 55ef068855 fix 2025-06-24 01:26:08 +02:00
vegard babbf2ed97 Workflow 2025-06-24 00:14:08 +02:00
vegard 8765a94893 Rename
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
vegard 54ade7cc49 rename
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
vegard bf666f0a89 rename
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
vegard b59fc563f3 rename
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
vegard 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
vegard bcf73d64bf Turn off logging for newly created portforward rules 2025-06-11 10:13:48 +02:00
vegard d372e4c7a7 Merge pull request #38 from vegardengen/37-optimize-api-usage
37 optimize api usage
2025-06-04 22:12:51 +02:00
vegard c80473d9e8 workaround for bug? 2025-06-04 22:02:48 +02:00
vegard bcffdfede7 Change leader election 2025-06-04 20:56:52 +02:00
vegard d7a444c8d7 Change an ID in Delete firewallgroup 2025-06-04 20:56:37 +02:00
vegard df9926e3da Small fix on updating firewall group/deleting component of it in Unifi 2025-06-04 19:10:03 +02:00
vegard c2ffce2d4d Do a few less updates 2025-06-04 18:29:26 +02:00
vegard fc0bda1e7b Merge pull request #36 from vegardengen/35-fix-portforward-logic
Check if portfoward already exists, and update if needed
2025-04-22 07:34:48 +02:00
46 changed files with 3360 additions and 128 deletions
+26
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
+50
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
+54
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
+56 -2
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
+5 -5
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"
+10 -4
View File
@@ -21,11 +21,13 @@ import (
"flag"
"os"
"path/filepath"
"time"
// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/utils/pointer"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
@@ -37,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
)
@@ -187,6 +189,10 @@ func main() {
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "f05533b6.engen.priv.no",
LeaseDuration: pointer.Duration(30 * time.Second),
RenewDeadline: pointer.Duration(20 * time.Second),
RetryPeriod: pointer.Duration(5 * time.Second),
// LeaderElectionReleaseOnCancel defines if the leader should step down voluntarily
// when the Manager ends. This requires the binary to immediately end when the
// Manager is stopped, otherwise, this setting is unsafe. Setting this significantly
+1 -1
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
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: []
+2 -3
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
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
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
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.
+23
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/
+16
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
+335
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.
@@ -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: {}
@@ -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: {}
@@ -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: {}
@@ -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: {}
@@ -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: {}
@@ -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 }}
@@ -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 }}
@@ -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 }}
@@ -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 }}
@@ -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 }}
@@ -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
@@ -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 }}
@@ -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 }}
@@ -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 }}
@@ -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 }}
@@ -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 }}
@@ -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 }}
+159
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
+17 -17
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
@@ -372,12 +372,12 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
for _, firewall_group := range firewall_groups {
if firewall_group.Name == ipv4_name {
if len(ipv4) == 0 {
log.Info(fmt.Sprintf("Delete %s", ipv4_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID)
log.Info(fmt.Sprintf("Delete %s: %s", ipv4_name, firewallGroup.Status.ResourcesManaged.IPV4Object.ID))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.IPV4Object.ID)
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"127.0.0.1"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -413,11 +413,11 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if firewall_group.Name == ipv6_name {
if len(ipv6) == 0 {
log.Info(fmt.Sprintf("Delete %s", ipv6_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID)
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.IPV6Object.ID)
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"::1"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -453,11 +453,11 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if firewall_group.Name == tcpports_name {
if len(tcpports) == 0 {
log.Info(fmt.Sprintf("Delete %s", tcpports_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID)
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.TCPPortsObject.ID)
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"0"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -493,11 +493,11 @@ func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req reconcile.R
if firewall_group.Name == udpports_name {
if len(udpports) == 0 {
log.Info(fmt.Sprintf("Delete %s", udpports_name))
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID)
err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewallGroup.Status.ResourcesManaged.UDPPortsObject.ID)
if err != nil {
msg := strings.ToLower(err.Error())
log.Info(msg)
if strings.Contains(msg, "api.err.objectreferredby") {
if strings.Contains(msg, "api.err.objectreferredby") || strings.Contains(msg, "invalid character") {
log.Info("Firewall group is in use. Invoking workaround...!")
firewall_group.GroupMembers = []string{"127.0.0.1"}
firewall_group.Name = firewall_group.Name + "-deleted"
@@ -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() {
@@ -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()
@@ -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() {
@@ -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
@@ -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() {
@@ -19,6 +19,7 @@ package controller
import (
"context"
"fmt"
"reflect"
"time"
"k8s.io/apimachinery/pkg/runtime"
@@ -27,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
@@ -111,10 +112,12 @@ func (r *NetworkconfigurationReconciler) Reconcile(ctx context.Context, req ctrl
Vlan: int64(unifinetwork.VLAN),
VlanEnabled: unifinetwork.VLANEnabled,
}
networkObj.Spec = networkSpec
err := r.Update(ctx, &networkObj)
if err != nil {
return ctrl.Result{}, err
if !reflect.DeepEqual(networkObj.Spec, networkSpec) {
networkObj.Spec = networkSpec
err := r.Update(ctx, &networkObj)
if err != nil {
return ctrl.Result{}, err
}
}
}
}
@@ -210,14 +213,19 @@ func (r *NetworkconfigurationReconciler) Reconcile(ctx context.Context, req ctrl
} else {
for _, networkCRD := range networkCRDs.Items {
if networkCRD.Spec.Name == unifinetwork.Name {
networkCRD.Spec = networkSpec
}
err := r.Update(ctx, &networkCRD)
if err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
if err = r.Status().Update(ctx, &networkCRD); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
if !reflect.DeepEqual(networkCRD.Spec, networkSpec) {
networkCRD.Spec = networkSpec
err := r.Update(ctx, &networkCRD)
if err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
if !reflect.DeepEqual(networkCRD.Status, networkStatus) {
networkCRD.Status = networkStatus
if err = r.Status().Update(ctx, &networkCRD); err != nil {
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
}
}
}
}
}
@@ -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() {
@@ -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 {
@@ -133,7 +133,7 @@ func (r *PortForwardReconciler) Reconcile(ctx context.Context, req ctrl.Request)
}
}
} else {
_, err := r.UnifiClient.Client.CreatePortForward(context.Background(), r.UnifiClient.SiteID, &goUnifi.PortForward{Name: portforwardname, PfwdInterface: "wan", Src: "any", Log: true, DestinationIPs: []goUnifi.PortForwardDestinationIPs{}, Enabled: true, Fwd: ip, DestinationIP: "any", Proto: "tcp", DstPort: fmt.Sprintf("%d", portMap[port.Name]), SiteID: r.UnifiClient.SiteID, FwdPort: fmt.Sprintf("%d", port.Port)})
_, err := r.UnifiClient.Client.CreatePortForward(context.Background(), r.UnifiClient.SiteID, &goUnifi.PortForward{Name: portforwardname, PfwdInterface: "wan", Src: "any", Log: false, DestinationIPs: []goUnifi.PortForwardDestinationIPs{}, Enabled: true, Fwd: ip, DestinationIP: "any", Proto: "tcp", DstPort: fmt.Sprintf("%d", portMap[port.Name]), SiteID: r.UnifiClient.SiteID, FwdPort: fmt.Sprintf("%d", port.Port)})
if err != nil {
log.Error(err, "Portforward could not be created")
return ctrl.Result{RequeueAfter: 10 * time.Minute}, err
@@ -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() {
+1 -1
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
)
+1 -1
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
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: ""