Compare commits

...

109 Commits

Author SHA1 Message Date
Mark Stickley c5e1158d6d
docs: Fixed numbering in quick_start.md (#777)
Signed-off-by: Mark Stickley <markstickley@users.noreply.github.com>
2025-08-07 14:10:30 -04:00
OpenFeature Bot 88a3ee2322
chore: release 0.8.7 (#769)
Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-07-28 22:55:12 +02:00
Yosiah de Koeyer 6f7152cffc
fix: API server warning for empty imagePullSecrets (#774)
Signed-off-by: Yosiah de Koeyer <dev@yosiahdekoeyer.dev>
2025-07-14 09:14:43 -04:00
Yosiah de Koeyer 6cbc0fa1a1
fix: Ingress annotations not reconciling (#773)
Signed-off-by: Yosiah de Koeyer <dev@yosiahdekoeyer.dev>
2025-07-14 09:14:25 -04:00
wrzasa 4b76e479c4
fix: end-to-end.yaml (#771)
Signed-off-by: wrzasa <wrzasa@users.noreply.github.com>
2025-06-26 19:45:33 +00:00
renovate[bot] 1e5af9d5f0
chore(deps): update actions/setup-node action to v4.4.0 (#767)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-13 15:23:56 -04:00
OpenFeature Bot 36a286c618
chore: release 0.8.6 (#752)
Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-06-13 13:39:34 +00:00
Oleg Atamanenko 349c176ee5
feat(flagd): add support for GCS (#765)
Signed-off-by: Oleg Atamanenko <oleg.atamanenko@gmail.com>
2025-06-03 15:57:32 +00:00
renovate[bot] 20f6f40956
fix(deps): update open-feature/flagd (#755)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-03 10:53:26 -04:00
Lukas Reining d39973b0ea
fix: namespace for ca injection for mutatingwebhook solving #759 (#763)
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-04-19 21:56:15 +02:00
renovate[bot] 301401391e
chore(deps): update dependency ubuntu to v24 (#748)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 08:12:42 -04:00
renovate[bot] a4b4216d20
fix(deps): update kubernetes packages to v0.32.3 (#756)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 08:12:27 -04:00
renovate[bot] 3fc56cd89d
chore(deps): update helm/kind-action action to v1.12.0 (#744)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-13 09:36:02 -04:00
Oleg Nenashev c4c0c59f7f
docs: Replace the old events calendar by the OpenFeature community Page link (#751)
Signed-off-by: Oleg Nenashev <o.v.nenashev@gmail.com>
2025-03-07 07:33:23 -05:00
github-actions[bot] 4929ef675b
chore: release 0.8.5 (#734)
Signed-off-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-01-31 13:20:16 -05:00
Todd Baert def1434060
chore: remove rbac-proxy values and doc (#742)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2025-01-31 13:11:50 -05:00
Michael Beemer 565b33a175
ci: run release please at the openfeature bot (#745)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-01-31 13:11:04 -05:00
renovate[bot] 3d2ddfe8d6
chore(deps): update docker/build-push-action action to v6 (#694)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 17:58:23 +00:00
renovate[bot] 06f43a9241
chore(deps): update golang docker tag to v1.23.5 (#481)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 17:23:18 +00:00
renovate[bot] 963d155d0a
chore(deps): update dependency bitnami-labs/readme-generator-for-helm to v2.7.0 (#741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 17:22:00 +00:00
Michael Beemer 2ed39efb01
ci: add dco workaround, run tests for merge queues (#740)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-01-31 12:13:37 -05:00
renovate[bot] 0038e45a72
chore(deps): update docker/login-action digest to 327cd5a (#728)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2025-01-31 12:10:41 -05:00
renovate[bot] 740205fc2a
chore(deps): update busybox docker tag to v1.37.0 (#739)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 12:10:22 -05:00
renovate[bot] 15d55c587d
chore(deps): update actions/setup-node action to v4.2.0 (#737)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2025-01-31 12:06:35 -05:00
renovate[bot] 8ac429beec
chore(deps): update aquasecurity/trivy-action action to v0.29.0 (#738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2025-01-31 12:05:39 -05:00
renovate[bot] 383c1168d4
chore(deps): update curlimages/curl docker tag to v8.11.1 (#703)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-31 12:04:42 -05:00
renovate[bot] 9eb1ca8beb
fix(deps): update open-feature/flagd (#736)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2025-01-31 11:58:44 -05:00
Lukas Reining 5358d1eacf
chore: replace deprecated gcr.io/kubebuilder/kube-rbac-proxy (#733)
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-01-30 12:20:47 -05:00
github-actions[bot] ee48ee418a
chore: release 0.8.4 (#732) 2025-01-14 07:42:36 +01:00
github-actions[bot] dbe12227bc
chore: release apis 0.2.45 (#727)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2025-01-13 16:52:19 -05:00
github-actions[bot] 31d7079da2
chore: release 0.8.3 (#731)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-13 11:44:03 -05:00
Lukas Reining 0aa61ec141
fix: flagd environment variables missing prefix (#730)
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-01-13 17:33:42 +01:00
hayden 674dd16ac4
fix: Add --port argument in flagd pods for set flagd service port (#710)
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-01-13 17:21:51 +01:00
github-actions[bot] 5b5769722c
chore: release 0.8.2 (#726)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-13 10:02:41 -05:00
Lukas Reining b393a2669c
feat: add gateway api support (#725)
Signed-off-by: Lukas Reining <lukas.reining@codecentric.de>
2025-01-13 15:48:16 +01:00
Marco Orovecchia e3f1e2471f
feat: allow setting mutating webhook failurepolicy and objectSelector via helm (#715)
Signed-off-by: Marco Orovecchia <marco@orovecchia.at>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Co-authored-by: Lukas Reining <lukas.reining@codecentric.de>
2025-01-13 14:57:04 +01:00
Woody Hill 9b8e8c322e
fix: Add missing poddisruptionbudget update verb (#722)
Signed-off-by: woodyh <woodyh@blackmagicdesign.com>
Co-authored-by: woodyh <woodyh@blackmagicdesign.com>
2025-01-13 08:53:18 -05:00
github-actions[bot] 838bddaabc
chore: release 0.8.1 (#720)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-10-30 12:24:27 -04:00
Matthias Riegler 8ae6ee81ac
fix: make flagd replica count configureable in helm chart (#716)
Signed-off-by: Matthias Riegler <matthias.riegler@ankorstore.com>
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-10-30 10:54:03 -04:00
Michael Beemer 52bac10723
ci(trivy): fetch vulnerabilities DB from ERC (#721)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-10-30 10:45:46 -04:00
Woody Hill 69efcf021d
fix: Add missing poddisruption budget permissions in manager cluster role (#718)
Signed-off-by: woodyh <woodyh@blackmagicdesign.com>
2024-10-30 09:02:47 -04:00
renovate[bot] 20e4045d1a
chore(deps): update docker/login-action digest to 0689575 (#714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-30 08:37:53 -04:00
github-actions[bot] bcdafd29a0
chore: release 0.8.0 (#708)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-24 14:11:37 -04:00
Matthias Riegler e115159936
feat: add flagd-proxy HA configuration (#712)
Signed-off-by: Matthias Riegler <matthias.riegler@ankorstore.com>
2024-10-22 16:16:35 -04:00
Michael Beemer 99b1cd46b3
ci: simplify ci, bump version, fix pr linter (#713)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-10-14 13:23:54 -04:00
renovate[bot] 696e2edf83
chore(deps): update golangci/golangci-lint-action action to v6 (#704)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-09 14:45:53 -04:00
hayden 64cdc25a03
fix!: Fix typo flagsValidatonEnabled into flagsValidationEnabled (#707)
Signed-off-by: kimsehwan96 <sktpghks138@gmail.com>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-10-02 11:39:50 -04:00
github-actions[bot] 7ace54d6a4
chore: release 0.7.2 (#701)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-12 14:49:09 -04:00
cpitstick-latai a21f278c2e
feat: Custom labels and annotations for namespace. (#702)
Signed-off-by: Christopher Pitstick <cpitstick@lat.ai>
2024-08-02 14:06:08 -04:00
renovate[bot] 1588ef8520
chore(deps): update codecov/codecov-action action to v4 (#693)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-02 12:33:52 -04:00
cpitstick-latai 4a43871bfa
fix: Case-align FROM and AS in Dockerfile (#699)
Co-authored-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-07-30 14:08:36 -04:00
cpitstick-latai b5ad5943cc
fix: Fix Kustomize installation (#700)
Signed-off-by: Christopher Pitstick <cpitstick@lat.ai>
2024-07-30 11:59:14 -04:00
github-actions[bot] 2c18afcba8
chore: release 0.7.1 (#687)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-23 14:29:28 -04:00
github-actions[bot] 9997ea443e
chore: release apis 0.2.44 (#688)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2024-07-23 13:55:43 -04:00
renovate[bot] b27a9eb716
chore(deps): update actions/setup-go action to v5 (#673)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 10:08:06 -04:00
renovate[bot] db53303d14
fix(deps): update golang.org/x/exp digest to 8a7402a (#691)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 10:07:52 -04:00
renovate[bot] 486a4fd8b2
chore(deps): update docker/login-action digest to 9780b0c (#605)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 09:50:08 -04:00
renovate[bot] 473929c3d8
chore(deps): update docker/metadata-action digest to 60a0d34 (#690)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 09:49:55 -04:00
renovate[bot] 6f77899bde
chore(deps): update actions/setup-node action to v4 (#675)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 09:49:41 -04:00
renovate[bot] 0fdd6db6e1
chore(deps): update module golang.org/x/net to v0.27.0 (#669)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-23 09:49:16 -04:00
renovate[bot] 0d331a9bc5
chore(deps): update open-feature/flagd (#689)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-07-23 09:26:30 -04:00
renovate[bot] 1d2713dad6
fix(deps): update module github.com/stretchr/testify to v1.9.0 (#671)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-07-18 16:02:45 -04:00
cpitstick-latai 7ec44a6a06
feat: Add labels and annotations to pods. (#681)
Signed-off-by: Christopher Pitstick <cpitstick@lat.ai>
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-07-18 15:51:38 -04:00
github-actions[bot] 917a680fb3
chore: release 0.7.0 (#685)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-08 12:22:54 -04:00
Todd Baert 65c3c26211
fix: remove duplicated port in helm (#686)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-07-04 07:54:37 -04:00
cpitstick-latai 31cddbaf95
feat!: split bind address to manage host and port separately (#679)
Signed-off-by: Christopher Pitstick <cpitstick@lat.ai>
2024-07-03 12:04:39 -04:00
cpitstick-latai 8e00a35c89
feat: Add hostNetwork flag. (#680)
Signed-off-by: Christopher Pitstick <cpitstick@lat.ai>
2024-06-28 13:46:47 -04:00
github-actions[bot] 339e5c8cf4
chore: release 0.6.1 (#661)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-06 14:54:21 -04:00
github-actions[bot] aed8ba19ff
chore: release apis 0.2.43 (#660)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-06 14:42:21 -04:00
renovate[bot] 1174a1b277
chore(deps): update open-feature/flagd (#670)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-06-06 11:33:55 -07:00
Kavindu Dodanduwa 499661e533
chore: add rule for env cfg tags (#674)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2024-06-06 14:12:29 -04:00
renovate[bot] 692a325f70
chore(deps): update dependency golangci/golangci-lint to v1.59.0 (#606)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 11:39:12 -04:00
renovate[bot] 60f528f464
chore(deps): update dependency kubernetes-sigs/controller-tools to v0.15.0 (#667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 10:55:07 -04:00
renovate[bot] e0b1748a26
chore(deps): update helm/kind-action action to v1.10.0 (#668)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 10:46:42 -04:00
renovate[bot] 28700ce600
chore(deps): update docker/metadata-action digest to f7b4ed1 (#598)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 10:46:20 -04:00
renovate[bot] fdce5f9a4a
chore(deps): update dependency bitnami-labs/readme-generator-for-helm to v2.6.1 (#662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 10:44:20 -04:00
renovate[bot] e43ce5f0a6
chore(deps): update actions/setup-node action to v3.8.2 (#580)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 10:44:07 -04:00
renovate[bot] ab7cfde2b8
chore(deps): update curlimages/curl docker tag to v8.8.0 (#616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-06 10:43:49 -04:00
Todd Baert df3d6d922a
fix: handle multiple imagePullSecrets (#666)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-06-06 08:52:20 -04:00
cpitstick-latai 2d7b30c407
feat: add image pull secrets (#655)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Christopher Pitstick <cpitstick@bluel3.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-06-04 15:26:02 -04:00
renovate[bot] 3746216b6e
fix(deps): update module go.uber.org/zap to v1.27.0 (#614)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-03 18:45:21 -04:00
renovate[bot] f245658ffb
fix(deps): update module github.com/go-logr/logr to v1.4.2 (#601)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-06-03 18:28:06 -04:00
Todd Baert aef1010dff
fix: flagd path defaults (#658)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-06-03 17:32:33 -04:00
Todd Baert dcab14a2c5
docs: require hosts, mention host-less rules (#659)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-06-03 16:12:23 -04:00
github-actions[bot] 7eaba4fa21
chore: release 0.6.0 (#653)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-29 15:49:40 -04:00
Todd Baert 640ff10c59
fix!: remove flagdResourceEnabled (#652)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-05-29 15:46:29 -04:00
github-actions[bot] 1ea457fdcb
chore: release 0.5.7 (#649)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-29 12:05:53 -04:00
github-actions[bot] b6cd29f787
chore: release apis 0.2.42 (#650)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-29 11:37:08 -04:00
odubajDT a18d27270e
chore: bump k8s libs (#644)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2024-05-29 11:20:44 -04:00
odubajDT 4f0477c8e0
fix: include parameters with default values to envVars (#648)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2024-05-29 10:55:57 -04:00
Florian Bacher e627f112e9
fix: adapt rolebinding to modified manager role (#647)
Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
2024-05-29 10:48:22 -04:00
github-actions[bot] 45651aeac1
chore: release 0.5.6 (#637)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-28 13:16:34 -04:00
github-actions[bot] 546635e6d4
chore: release apis 0.2.41 (#627)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-28 13:00:06 -04:00
odubajDT 972182539e
docs: support in-process evaluation (#640)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Signed-off-by: odubajDT <93584209+odubajDT@users.noreply.github.com>
Co-authored-by: Florian Bacher <florian.bacher@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2024-05-28 11:18:36 -04:00
odubajDT 51db913bc7
feat: introduce new CRD for in-process evaluation (#632)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Signed-off-by: odubajDT <93584209+odubajDT@users.noreply.github.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
Co-authored-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com>
2024-05-27 08:00:15 -04:00
Florian Bacher a8b7ad49d8
fix: use flagd standalone tag instead of sidecar tag for flagd deployments (#643)
Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
2024-05-23 14:05:00 +02:00
Florian Bacher 06b399e0cf
docs: document new Flagd CRD (#641)
Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
Co-authored-by: Giovanni Liva <giovanni.liva@dynatrace.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2024-05-23 07:44:47 -04:00
odubajDT dd23123987
test: use kyverno/chainsaw for E2E testing (#642)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2024-05-23 07:37:53 -04:00
Todd Baert d54914460b
fix: helm sidecar resources not applied (#639)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2024-05-15 09:32:30 -04:00
Florian Bacher b0b99a7d10
feat: add `flagd` CRD with ingress support (#633)
Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
Co-authored-by: odubajDT <93584209+odubajDT@users.noreply.github.com>
2024-05-15 07:17:59 +02:00
Florian Bacher 65e20cf72b
chore: init workspace before linting (#638)
Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
2024-05-14 11:48:46 -04:00
odubajDT b21378e4e5
fix: inject env variables to all pod containers (#634)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2024-05-14 07:18:33 +02:00
github-actions[bot] 275fe4e67e
chore: release 0.5.5 (#612)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-13 12:52:33 -04:00
Florian Bacher 04795403f6
chore: use workspaces to make api changes easier (#635)
Signed-off-by: Florian Bacher <florian.bacher@dynatrace.com>
2024-05-13 12:46:13 -04:00
odubajDT 2c39428259
chore: update API to the latest version (#631)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2024-05-06 09:02:14 -04:00
odubajDT c4831a3cdc
feat: introduce validating webhook for FeatureFlag CR (#622)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Signed-off-by: odubajDT <93584209+odubajDT@users.noreply.github.com>
Co-authored-by: Kavindu Dodanduwa <Kavindu-Dodan@users.noreply.github.com>
2024-05-06 14:52:12 +02:00
Esten Rye a40e13b421
fix: Add capability to skip crd installation during helm install (#625)
Signed-off-by: Esten Rye <esten.rye@ryezone.com>
2024-04-24 22:08:25 -04:00
odubajDT 918a69732f
chore: bump operator builder tools versions (#626)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2024-04-24 07:15:18 -07:00
Martin Coetzee bcc5912042
feat: operator interval (#621)
Signed-off-by: martin.coetzee <martin.coetzee@team.telstra.com>
Co-authored-by: martin.coetzee <martin.coetzee@team.telstra.com>
2024-04-23 15:13:23 -07:00
201 changed files with 22221 additions and 3025 deletions

10
.chainsaw-local.yaml Normal file
View File

@ -0,0 +1,10 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha1.json
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Configuration
metadata:
name: configuration-local
spec:
template: true
timeouts:
assert: 2m
error: 2m

11
.chainsaw.yaml Normal file
View File

@ -0,0 +1,11 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/configuration-chainsaw-v1alpha1.json
apiVersion: chainsaw.kyverno.io/v1alpha1
kind: Configuration
metadata:
name: configuration
spec:
skipDelete: true
template: true
timeouts:
assert: 2m
error: 2m

View File

@ -9,7 +9,7 @@
# Node >=16
# renovate: datasource=github-releases depName=bitnami-labs/readme-generator-for-helm
GENERATOR_VERSION="2.6.0"
GENERATOR_VERSION="2.7.0"
echo "Checking if readme generator is installed already..."
if [[ $(npm list -g | grep -c "readme-generator-for-helm@${GENERATOR_VERSION}") -eq 0 ]]; then

34
.github/scripts/strip-kustomize-helm.sh vendored Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
# This script is a hack to support helm flow control in kustomize overlays, which would otherwise break them.
# It allows us to render helm template bindings and add newlines.
# For instance, it transforms "___{{ .Value.myValue }}___" to {{ .Value.myValue }}.
# It also adds newlines wherever ___newline___ is found, and other operations. See
# sed_expressions below.
echo 'Running strip-kustomize-helm.sh script'
CHARTS_DIR='./chart/open-feature-operator/templates'
# Careful! Ordering of these expressions matter!
sed_expressions=(
"s/___newline___/\\n/g"
"s/___space___/ /g"
"s/\"___//g"
"s/___\"//g"
"/___delete_me___/d"
"s/___//g"
)
find $CHARTS_DIR -name "*.yaml" | while read file; do
for expr in "${sed_expressions[@]}"; do
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS (BSD) version
sed -i '' "$expr" "$file"
else
# Linux (GNU) version
sed -i "$expr" "$file"
fi
done
done
echo 'Done running strip-kustomize-helm.sh script'

12
.github/workflows/dco-merge-group.yml vendored Normal file
View File

@ -0,0 +1,12 @@
name: DCO
on:
merge_group:
# Workaround because the DCO app doesn't run on a merge_group trigger
# https://github.com/dcoapp/app/pull/200
jobs:
DCO:
runs-on: ubuntu-latest
if: ${{ github.actor != 'renovate[bot]' }}
steps:
- run: echo "dummy DCO workflow (it won't run any check actually) to trigger by merge_group in order to enable merge queue"

70
.github/workflows/e2e.yml vendored Normal file
View File

@ -0,0 +1,70 @@
name: E2E-Test
on:
workflow_call:
inputs:
kind_tag:
description: "Tag of Kind image"
type: "string"
env:
GO_VERSION: "~1.23"
defaults:
run:
shell: bash
jobs:
e2e-test:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download image
uses: actions/download-artifact@v4
with:
name: open-feature-operator-local-${{ github.sha }}
path: ${{ github.workspace }}
- name: Cache build tools
id: cache-build-tools
uses: actions/cache@v4
with:
path: ./bin
key: build-tools-${{ github.ref_name }}
- name: Load open-feature-operator image into docker
run: |
docker load --input ${{ github.workspace }}/open-feature-operator-local.tar
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1.12.0
with:
config: ./test/e2e/kind-cluster.yml
cluster_name: open-feature-operator-test
node_image: kindest/node:${{ inputs.kind_tag }}
- name: Load open-feature-operator image into Kind cluster
run: |
kind load docker-image open-feature-operator-local:${{ github.sha }} --name open-feature-operator-test
- name: Install Chainsaw
uses: kyverno/action-install-chainsaw@f2b47b97dc889c12702113753d713f01ec268de5 # v0.2.12
- name: Install OFO
run: |
IMG=open-feature-operator-local:${{ github.sha }} make deploy-operator
- name: Run e2e test
run: |
make e2e-test-chainsaw
- name: Create reports
if: failure()
working-directory: ./.github/scripts
run: ./create-reports.sh
- name: Upload cluster logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-tests
path: .github/scripts/logs

View File

@ -17,25 +17,28 @@ on:
- "!docs/**"
env:
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_VERSION: "v1.55.2"
GO_VERSION: "~1.21"
GOLANGCI_LINT_VERSION: "v1.63.4"
GO_VERSION: "~1.23"
jobs:
golangci-lint:
name: golangci-lint
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
strategy:
fail-fast: false
steps:
- name: Check out code
uses: actions/checkout@v4
- uses: actions/setup-go@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
- name: Workspace Init
run: make workspace-init
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v6
with:
working-directory: ./
version: ${{ env.GOLANGCI_LINT_VERSION }}

View File

@ -4,16 +4,14 @@ on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
env:
# Default minimum version of Go to support.
DEFAULT_GO_VERSION: "~1.21"
# renovate: datasource=github-tags depName=kudobuilder/kuttl
KUTTL_VERSION: "v0.15.0"
types:
- opened
- synchronize
- reopened
branches:
- main
merge_group:
permissions:
contents: read
@ -21,12 +19,15 @@ permissions:
jobs:
unit-test:
name: Unit Tests
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ env.DEFAULT_GO_VERSION }}
go-version-file: 'go.mod'
- name: Setup Environment
run: |
@ -41,33 +42,34 @@ jobs:
path: ~/go/pkg/mod
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/go.sum') }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Workspace Init
run: make workspace-init
- name: Unit Test
run: make unit-test
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
with:
flags: unit-tests
docker-local:
permissions:
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@master
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@master
uses: docker/setup-buildx-action@v3
- name: Build
uses: docker/build-push-action@v4
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
@ -76,78 +78,32 @@ jobs:
cache-from: type=gha,scope=${{ github.ref_name }}-ofo
cache-to: type=gha,scope=${{ github.ref_name }}-ofo
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
uses: aquasecurity/trivy-action@0.29.0
with:
input: /github/workspace/open-feature-operator-local.tar
format: "template"
template: "@/contrib/sarif.tpl"
input: ${{ github.workspace }}/open-feature-operator-local.tar
format: "sarif"
output: "trivy-results.sarif"
severity: "CRITICAL,HIGH"
env:
# use an alternative trivvy db to avoid rate limits
TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db:2,ghcr.io/aquasecurity/trivy-db:2
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: "trivy-results.sarif"
- name: Upload image as artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: open-feature-operator-local-${{ github.sha }}
path: ${{ github.workspace }}/open-feature-operator-local.tar
e2e-test:
runs-on: ubuntu-22.04
needs: docker-local
e2e_tests:
name: E2E Tests
needs:
- docker-local
strategy:
matrix:
node_image: [ v1.22.17, v1.23.17, v1.24.15, v1.25.11, v1.26.3, v1.27.3, v1.28.0 ]
steps:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ${{ env.DEFAULT_GO_VERSION }}
- name: Checkout
uses: actions/checkout@v4
- name: Download image
uses: actions/download-artifact@v3
with:
name: open-feature-operator-local-${{ github.sha }}
path: ${{ github.workspace }}
- name: Cache build tools
id: cache-build-tools
uses: actions/cache@v4
with:
path: ./bin
key: build-tools-${{ github.ref_name }}
- name: Load open-feature-operator image into docker
run: |
docker load --input ${{ github.workspace }}/open-feature-operator-local.tar
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1.9.0
with:
config: ./test/e2e/kind-cluster.yml
cluster_name: open-feature-operator-test
node_image: kindest/node:${{ matrix.node_image }}
- name: Download KUTTL
run: |
curl -fL https://github.com/kudobuilder/kuttl/releases/download/${{ env.KUTTL_VERSION }}/kubectl-kuttl_${KUTTL_VERSION#v}_linux_x86_64 -o kubectl-kuttl
chmod +x kubectl-kuttl
mv kubectl-kuttl /usr/local/bin
- name: Load open-feature-operator image into Kind cluster
run: |
kind load docker-image open-feature-operator-local:${{ github.sha }} --name open-feature-operator-test
- name: Run e2e test
run: |
IMG=open-feature-operator-local:${{ github.sha }} make deploy-operator
IMG=open-feature-operator-local:${{ github.sha }} make e2e-test-kuttl
- name: Create reports
if: failure()
working-directory: ./.github/scripts
run: ./create-reports.sh
- name: Upload cluster logs
if: failure()
uses: actions/upload-artifact@v3
with:
name: e2e-tests
path: .github/scripts/logs
kind_tag: [ v1.22.17, v1.23.17, v1.24.15, v1.25.11, v1.26.3, v1.27.3, v1.28.0 ]
with:
kind_tag: ${{ matrix.kind_tag }}
uses: ./.github/workflows/e2e.yml

View File

@ -18,9 +18,10 @@ jobs:
pull-requests: write
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
name: Validate PR title
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- uses: amannn/action-semantic-pull-request@v5
id: lint_pr_title
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -7,7 +7,7 @@ on:
env:
# Default minimum version of Go to support.
DEFAULT_GO_VERSION: "~1.21"
DEFAULT_GO_VERSION: "~1.23"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
GITHUB_PAGES_BRANCH: gh-pages
@ -24,7 +24,7 @@ jobs:
permissions:
contents: write # for google-github-actions/release-please-action to create release commit
pull-requests: write # for google-github-actions/release-please-action to create release PR
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
# Release-please creates a PR that tracks all changes
steps:
@ -32,8 +32,9 @@ jobs:
id: release
with:
command: manifest
token: ${{secrets.GITHUB_TOKEN}}
token: ${{secrets.RELEASE_PLEASE_ACTION_TOKEN}}
default-branch: main
signoff: "OpenFeature Bot <109696520+openfeaturebot@users.noreply.github.com>"
outputs:
release_created: ${{ steps.release.outputs.release_created }}
@ -43,7 +44,7 @@ jobs:
needs: release-please
permissions:
packages: write # to push the container image
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ needs.release-please.outputs.release_created }}
steps:
- name: Checkout
@ -52,7 +53,7 @@ jobs:
ref: ${{ needs.release-please.outputs.release_tag_name }}
- name: Log in to the Container registry
uses: docker/login-action@a9794064588be971151ec5e7144cb535bcb56e36
uses: docker/login-action@327cd5a69de6c009b9ce71bce8395f28e651bf99
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
@ -60,7 +61,7 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@31cebacef4805868f9ce9a0cb03ee36c32df2ac4
uses: docker/metadata-action@60a0d343a0d8a18aedee9d34e62251f752153bdb
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
@ -74,7 +75,7 @@ jobs:
uses: docker/setup-buildx-action@master
- name: Build
uses: docker/build-push-action@v4
uses: docker/build-push-action@v6
with:
builder: ${{ steps.buildx.outputs.name }}
context: .
@ -109,7 +110,7 @@ jobs:
needs: release-please
permissions:
contents: write # for softprops/action-gh-release to create GitHub release
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ needs.release-please.outputs.release_created }}
steps:
- name: Checkout
@ -118,10 +119,11 @@ jobs:
ref: ${{ needs.release-please.outputs.release_tag_name }}
- name: Setup go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ env.DEFAULT_GO_VERSION }}
- run: |
make workspace-init
go mod tidy
make controller-gen
IMG=ghcr.io/open-feature/open-feature-operator:${{ needs.release-please.outputs.release_tag_name }} make helm-package
@ -144,7 +146,7 @@ jobs:
needs: release-please
permissions:
contents: write
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ needs.release-please.outputs.release_created }}
steps:
- name: Checkout
@ -154,7 +156,7 @@ jobs:
ref: ${{ env.GITHUB_PAGES_BRANCH }}
- name: Setup go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ env.DEFAULT_GO_VERSION }}

View File

@ -9,7 +9,7 @@ defaults:
jobs:
check-helm-docs:
name: Check crd documentation values
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Check out code
uses: actions/checkout@v4

View File

@ -11,13 +11,13 @@ defaults:
jobs:
check-helm-docs:
name: Check helm documentation values
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v3.8.1
uses: actions/setup-node@v4.4.0
with:
node-version: 16

3
.gitignore vendored
View File

@ -2,6 +2,7 @@ config/rendered/release.yaml
.tar.gz
config/manager/manager.yaml
config/manager/kustomization.yaml
readme-generator-for-helm
tmpcrd.yaml
schemas
.vscode
@ -33,3 +34,5 @@ testbin/*
go.work
go.work.sum
dist

View File

@ -1,6 +1,6 @@
run:
timeout: 5m
go: '1.20'
go: '1.23'
linters:
enable:
- gofmt # Gofmt checks whether code was gofmt-ed. By default, this tool runs with -s option to check for code simplification

View File

@ -1,4 +1,4 @@
{
".": "0.5.4",
"apis": "0.2.40"
".": "0.8.7",
"apis": "0.2.45"
}

View File

@ -1,5 +1,297 @@
# Changelog
## [0.8.7](https://github.com/open-feature/open-feature-operator/compare/v0.8.6...v0.8.7) (2025-07-14)
### 🐛 Bug Fixes
* API server warning for empty imagePullSecrets ([#774](https://github.com/open-feature/open-feature-operator/issues/774)) ([6f7152c](https://github.com/open-feature/open-feature-operator/commit/6f7152cffc75b1b00a4f941afc9e8ee2593151d7))
* end-to-end.yaml ([#771](https://github.com/open-feature/open-feature-operator/issues/771)) ([4b76e47](https://github.com/open-feature/open-feature-operator/commit/4b76e479c44c3dd90ab237ac7ba319617b61f6b9))
* Ingress annotations not reconciling ([#773](https://github.com/open-feature/open-feature-operator/issues/773)) ([6cbc0fa](https://github.com/open-feature/open-feature-operator/commit/6cbc0fa1a19ef89660b0816b0e92425d1e414d96))
### 🧹 Chore
* **deps:** update actions/setup-node action to v4.4.0 ([#767](https://github.com/open-feature/open-feature-operator/issues/767)) ([1e5af9d](https://github.com/open-feature/open-feature-operator/commit/1e5af9d5f0933d93fb55c8df0c6e2b463fae4b4c))
## [0.8.6](https://github.com/open-feature/open-feature-operator/compare/v0.8.5...v0.8.6) (2025-06-03)
### ✨ New Features
* **flagd:** add support for GCS ([#765](https://github.com/open-feature/open-feature-operator/issues/765)) ([349c176](https://github.com/open-feature/open-feature-operator/commit/349c176ee5eb9f2738f1354c8987760620363aa6))
### 🐛 Bug Fixes
* **deps:** update kubernetes packages to v0.32.3 ([#756](https://github.com/open-feature/open-feature-operator/issues/756)) ([a4b4216](https://github.com/open-feature/open-feature-operator/commit/a4b4216d2009a5703214cfb9efacea60d9e1f8d0))
* **deps:** update open-feature/flagd ([#755](https://github.com/open-feature/open-feature-operator/issues/755)) ([20f6f40](https://github.com/open-feature/open-feature-operator/commit/20f6f4095669e4b0b0f895da683a2fe9e580ee5e))
* namespace for ca injection for mutatingwebhook solving [#759](https://github.com/open-feature/open-feature-operator/issues/759) ([#763](https://github.com/open-feature/open-feature-operator/issues/763)) ([d39973b](https://github.com/open-feature/open-feature-operator/commit/d39973b0ea9801829d146ad7649a2b25985fb7af))
### 🧹 Chore
* **deps:** update dependency ubuntu to v24 ([#748](https://github.com/open-feature/open-feature-operator/issues/748)) ([3014013](https://github.com/open-feature/open-feature-operator/commit/301401391ec352a4e23ba96a479aad0a42ddb07f))
* **deps:** update helm/kind-action action to v1.12.0 ([#744](https://github.com/open-feature/open-feature-operator/issues/744)) ([3fc56cd](https://github.com/open-feature/open-feature-operator/commit/3fc56cd89d3f220f8131184fbe4e9245f554c680))
### 📚 Documentation
* Replace the old events calendar by the OpenFeature community Page link ([#751](https://github.com/open-feature/open-feature-operator/issues/751)) ([c4c0c59](https://github.com/open-feature/open-feature-operator/commit/c4c0c59f7f522c8c2f4d3f7fed57dd1cda4e92bb))
## [0.8.5](https://github.com/open-feature/open-feature-operator/compare/v0.8.4...v0.8.5) (2025-01-31)
### 🐛 Bug Fixes
* **deps:** update open-feature/flagd ([#736](https://github.com/open-feature/open-feature-operator/issues/736)) ([9eb1ca8](https://github.com/open-feature/open-feature-operator/commit/9eb1ca8bebe6cfc5d33a905e610ea8a908381740))
### 🧹 Chore
* **deps:** update actions/setup-node action to v4.2.0 ([#737](https://github.com/open-feature/open-feature-operator/issues/737)) ([15d55c5](https://github.com/open-feature/open-feature-operator/commit/15d55c587d6edee562bd86564fa60bb559eed132))
* **deps:** update aquasecurity/trivy-action action to v0.29.0 ([#738](https://github.com/open-feature/open-feature-operator/issues/738)) ([8ac429b](https://github.com/open-feature/open-feature-operator/commit/8ac429beeced6d06883fa66de0e9a50819986f69))
* **deps:** update busybox docker tag to v1.37.0 ([#739](https://github.com/open-feature/open-feature-operator/issues/739)) ([740205f](https://github.com/open-feature/open-feature-operator/commit/740205fc2a6a89dcf2572d9f604f7ba69afc6573))
* **deps:** update curlimages/curl docker tag to v8.11.1 ([#703](https://github.com/open-feature/open-feature-operator/issues/703)) ([383c116](https://github.com/open-feature/open-feature-operator/commit/383c1168d4640d2fe57782982829f68d349b1828))
* **deps:** update dependency bitnami-labs/readme-generator-for-helm to v2.7.0 ([#741](https://github.com/open-feature/open-feature-operator/issues/741)) ([963d155](https://github.com/open-feature/open-feature-operator/commit/963d155d0a847718a9bde15b6e90e56b09812ebb))
* **deps:** update docker/build-push-action action to v6 ([#694](https://github.com/open-feature/open-feature-operator/issues/694)) ([3d2ddfe](https://github.com/open-feature/open-feature-operator/commit/3d2ddfe8d6b2b9b31ba6100f008d079b5e42d19c))
* **deps:** update docker/login-action digest to 327cd5a ([#728](https://github.com/open-feature/open-feature-operator/issues/728)) ([0038e45](https://github.com/open-feature/open-feature-operator/commit/0038e45a72f088976378d647d2ccf721182e0318))
* **deps:** update golang docker tag to v1.23.5 ([#481](https://github.com/open-feature/open-feature-operator/issues/481)) ([06f43a9](https://github.com/open-feature/open-feature-operator/commit/06f43a9241fda9700ef6d6361a65dc50fac7ecb3))
* remove rbac-proxy values and doc ([#742](https://github.com/open-feature/open-feature-operator/issues/742)) ([def1434](https://github.com/open-feature/open-feature-operator/commit/def14340603c2c9976e3a6142ab494764933f682))
* replace deprecated gcr.io/kubebuilder/kube-rbac-proxy ([#733](https://github.com/open-feature/open-feature-operator/issues/733)) ([5358d1e](https://github.com/open-feature/open-feature-operator/commit/5358d1eacfd44cf01016c4bc6f68c496e757354f))
## [0.8.4](https://github.com/open-feature/open-feature-operator/compare/v0.8.3...v0.8.4) (2025-01-13)
### 🧹 Chore
* release apis 0.2.45 ([#727](https://github.com/open-feature/open-feature-operator/issues/727)) ([dbe1222](https://github.com/open-feature/open-feature-operator/commit/dbe12227bc551dcda472b6c1afedb57321852e33))
## [0.8.3](https://github.com/open-feature/open-feature-operator/compare/v0.8.2...v0.8.3) (2025-01-13)
### 🐛 Bug Fixes
* Add --port argument in flagd pods for set flagd service port ([#710](https://github.com/open-feature/open-feature-operator/issues/710)) ([674dd16](https://github.com/open-feature/open-feature-operator/commit/674dd16ac4dca94f04160247c55121e266979e25))
* flagd environment variables missing prefix ([#730](https://github.com/open-feature/open-feature-operator/issues/730)) ([0aa61ec](https://github.com/open-feature/open-feature-operator/commit/0aa61ec1419ec1d99f3c875dd6526ec8ca8e6014))
## [0.8.2](https://github.com/open-feature/open-feature-operator/compare/v0.8.1...v0.8.2) (2025-01-13)
### ✨ New Features
* add gateway api support ([#725](https://github.com/open-feature/open-feature-operator/issues/725)) ([b393a26](https://github.com/open-feature/open-feature-operator/commit/b393a2669c05d58afe453867401f8d697464b145))
* allow setting mutating webhook failurepolicy and objectSelector via helm ([#715](https://github.com/open-feature/open-feature-operator/issues/715)) ([e3f1e24](https://github.com/open-feature/open-feature-operator/commit/e3f1e2471f2f2bd1a29539c57aa8161dc9fdd570))
### 🐛 Bug Fixes
* Add missing poddisruptionbudget update verb ([#722](https://github.com/open-feature/open-feature-operator/issues/722)) ([9b8e8c3](https://github.com/open-feature/open-feature-operator/commit/9b8e8c322ecc07d4d7f85d491a5cae0187b2db92))
## [0.8.1](https://github.com/open-feature/open-feature-operator/compare/v0.8.0...v0.8.1) (2024-10-30)
### 🐛 Bug Fixes
* Add missing poddisruption budget permissions in manager cluster role ([#718](https://github.com/open-feature/open-feature-operator/issues/718)) ([69efcf0](https://github.com/open-feature/open-feature-operator/commit/69efcf021dfa4915bba9c943d0b8a8d137bfb2b2))
* make flagd replica count configureable in helm chart ([#716](https://github.com/open-feature/open-feature-operator/issues/716)) ([8ae6ee8](https://github.com/open-feature/open-feature-operator/commit/8ae6ee81ac48589d01fd6e75f9c16bcd62c336b0))
### 🧹 Chore
* **deps:** update docker/login-action digest to 0689575 ([#714](https://github.com/open-feature/open-feature-operator/issues/714)) ([20e4045](https://github.com/open-feature/open-feature-operator/commit/20e4045d1ad45a5047f4f81a544b96643528dda7))
## [0.8.0](https://github.com/open-feature/open-feature-operator/compare/v0.7.2...v0.8.0) (2024-10-22)
### ⚠ BREAKING CHANGES
* Fix typo flagsValidatonEnabled into flagsValidationEnabled ([#707](https://github.com/open-feature/open-feature-operator/issues/707))
### ✨ New Features
* add flagd-proxy HA configuration ([#712](https://github.com/open-feature/open-feature-operator/issues/712)) ([e115159](https://github.com/open-feature/open-feature-operator/commit/e115159936773e11353912bb11739a51108eb297))
### 🐛 Bug Fixes
* Fix typo flagsValidatonEnabled into flagsValidationEnabled ([#707](https://github.com/open-feature/open-feature-operator/issues/707)) ([64cdc25](https://github.com/open-feature/open-feature-operator/commit/64cdc25a031cd6991cca9425ec3052fc892ce720))
### 🧹 Chore
* **deps:** update golangci/golangci-lint-action action to v6 ([#704](https://github.com/open-feature/open-feature-operator/issues/704)) ([696e2ed](https://github.com/open-feature/open-feature-operator/commit/696e2edf83a6ba358bf6e19337e69c7b70162d37))
## [0.7.2](https://github.com/open-feature/open-feature-operator/compare/v0.7.1...v0.7.2) (2024-08-02)
### ✨ New Features
* Custom labels and annotations for namespace. ([#702](https://github.com/open-feature/open-feature-operator/issues/702)) ([a21f278](https://github.com/open-feature/open-feature-operator/commit/a21f278c2ee994223eb715796c963d109237dff5))
### 🐛 Bug Fixes
* Case-align FROM and AS in Dockerfile ([#699](https://github.com/open-feature/open-feature-operator/issues/699)) ([4a43871](https://github.com/open-feature/open-feature-operator/commit/4a43871bfacbd9b38a0225b50520daa37bef97c9))
* Fix Kustomize installation ([#700](https://github.com/open-feature/open-feature-operator/issues/700)) ([b5ad594](https://github.com/open-feature/open-feature-operator/commit/b5ad5943cc0edf4298efa571a50482f8991314e9))
### 🧹 Chore
* **deps:** update codecov/codecov-action action to v4 ([#693](https://github.com/open-feature/open-feature-operator/issues/693)) ([1588ef8](https://github.com/open-feature/open-feature-operator/commit/1588ef85202c14fb2bcf47925f99bb2ab5dd1ac3))
## [0.7.1](https://github.com/open-feature/open-feature-operator/compare/v0.7.0...v0.7.1) (2024-07-23)
### ✨ New Features
* Add labels and annotations to pods. ([#681](https://github.com/open-feature/open-feature-operator/issues/681)) ([7ec44a6](https://github.com/open-feature/open-feature-operator/commit/7ec44a6a06ce570bf80d2cf6d78632f61a73fe89))
### 🐛 Bug Fixes
* **deps:** update golang.org/x/exp digest to 8a7402a ([#691](https://github.com/open-feature/open-feature-operator/issues/691)) ([db53303](https://github.com/open-feature/open-feature-operator/commit/db53303d14ca0fada38db97981dd5ed95d95f7ad))
* **deps:** update module github.com/stretchr/testify to v1.9.0 ([#671](https://github.com/open-feature/open-feature-operator/issues/671)) ([1d2713d](https://github.com/open-feature/open-feature-operator/commit/1d2713dad6381e56aa3b552c33e1cb3513574a6e))
### 🧹 Chore
* **deps:** update actions/setup-go action to v5 ([#673](https://github.com/open-feature/open-feature-operator/issues/673)) ([b27a9eb](https://github.com/open-feature/open-feature-operator/commit/b27a9eb7163b23c4febec9721126639297a41217))
* **deps:** update actions/setup-node action to v4 ([#675](https://github.com/open-feature/open-feature-operator/issues/675)) ([6f77899](https://github.com/open-feature/open-feature-operator/commit/6f77899bdefefdf43f4cee02c6f1def3ccaf758a))
* **deps:** update docker/login-action digest to 9780b0c ([#605](https://github.com/open-feature/open-feature-operator/issues/605)) ([486a4fd](https://github.com/open-feature/open-feature-operator/commit/486a4fd8b2d647d1666f745ed07a601fcc8b7af8))
* **deps:** update docker/metadata-action digest to 60a0d34 ([#690](https://github.com/open-feature/open-feature-operator/issues/690)) ([473929c](https://github.com/open-feature/open-feature-operator/commit/473929c3d80f1abe9a9dd92e5a4db542c8b32da8))
* **deps:** update module golang.org/x/net to v0.27.0 ([#669](https://github.com/open-feature/open-feature-operator/issues/669)) ([0fdd6db](https://github.com/open-feature/open-feature-operator/commit/0fdd6db6e1809f3e94fe68ca6d3094725ce51b4c))
* **deps:** update open-feature/flagd ([#689](https://github.com/open-feature/open-feature-operator/issues/689)) ([0d331a9](https://github.com/open-feature/open-feature-operator/commit/0d331a9bc5db752cb3aa49f7ce5afc0830f115fe))
* release apis 0.2.44 ([#688](https://github.com/open-feature/open-feature-operator/issues/688)) ([9997ea4](https://github.com/open-feature/open-feature-operator/commit/9997ea443ecc025afd7aff2e33e92fb05acb3b1a))
## [0.7.0](https://github.com/open-feature/open-feature-operator/compare/v0.6.1...v0.7.0) (2024-07-04)
### ⚠ BREAKING CHANGES
* split bind address to manage host and port separately ([#679](https://github.com/open-feature/open-feature-operator/issues/679))
### ✨ New Features
* Add hostNetwork flag. ([#680](https://github.com/open-feature/open-feature-operator/issues/680)) ([8e00a35](https://github.com/open-feature/open-feature-operator/commit/8e00a35c89732a1b76ab07a923ae7aee13028615))
* split bind address to manage host and port separately ([#679](https://github.com/open-feature/open-feature-operator/issues/679)) ([31cddba](https://github.com/open-feature/open-feature-operator/commit/31cddbaf95649701a5c981e8fd0c1f0a5461e980))
### 🐛 Bug Fixes
* remove duplicated port in helm ([#686](https://github.com/open-feature/open-feature-operator/issues/686)) ([65c3c26](https://github.com/open-feature/open-feature-operator/commit/65c3c262110cca3b1d913b680e4b49973ce1a09a))
## [0.6.1](https://github.com/open-feature/open-feature-operator/compare/v0.6.0...v0.6.1) (2024-06-06)
### ✨ New Features
* add image pull secrets ([#655](https://github.com/open-feature/open-feature-operator/issues/655)) ([2d7b30c](https://github.com/open-feature/open-feature-operator/commit/2d7b30c407f5c4d83cdf5bb08ff9de52bcc841a2))
### 🐛 Bug Fixes
* **deps:** update module github.com/go-logr/logr to v1.4.2 ([#601](https://github.com/open-feature/open-feature-operator/issues/601)) ([f245658](https://github.com/open-feature/open-feature-operator/commit/f245658ffbc33db5814798182a1e7d9a538ba4e8))
* **deps:** update module go.uber.org/zap to v1.27.0 ([#614](https://github.com/open-feature/open-feature-operator/issues/614)) ([3746216](https://github.com/open-feature/open-feature-operator/commit/3746216b6e3c7b20dff2788954eb11e94e8a4a34))
* flagd path defaults ([#658](https://github.com/open-feature/open-feature-operator/issues/658)) ([aef1010](https://github.com/open-feature/open-feature-operator/commit/aef1010dff162e8d232942e642c68e3e9ba3f35f))
* handle multiple imagePullSecrets ([#666](https://github.com/open-feature/open-feature-operator/issues/666)) ([df3d6d9](https://github.com/open-feature/open-feature-operator/commit/df3d6d922a262ccfe3082a972a8f3fe495a7d4ca))
### 🧹 Chore
* add rule for env cfg tags ([#674](https://github.com/open-feature/open-feature-operator/issues/674)) ([499661e](https://github.com/open-feature/open-feature-operator/commit/499661e53318f7476e9cb4c9a551eb0c3a626090))
* **deps:** update actions/setup-node action to v3.8.2 ([#580](https://github.com/open-feature/open-feature-operator/issues/580)) ([e43ce5f](https://github.com/open-feature/open-feature-operator/commit/e43ce5f0a6e207b3f03262d29b1ab0a5e6baa817))
* **deps:** update curlimages/curl docker tag to v8.8.0 ([#616](https://github.com/open-feature/open-feature-operator/issues/616)) ([ab7cfde](https://github.com/open-feature/open-feature-operator/commit/ab7cfde2b8bc284f7d67fdc69ff5a7bad6665790))
* **deps:** update dependency bitnami-labs/readme-generator-for-helm to v2.6.1 ([#662](https://github.com/open-feature/open-feature-operator/issues/662)) ([fdce5f9](https://github.com/open-feature/open-feature-operator/commit/fdce5f9a4a4faa5618ffa1bed7f7058d0354e7ad))
* **deps:** update dependency golangci/golangci-lint to v1.59.0 ([#606](https://github.com/open-feature/open-feature-operator/issues/606)) ([692a325](https://github.com/open-feature/open-feature-operator/commit/692a325f70bb902a1b51e44efd5ce004bb832c05))
* **deps:** update dependency kubernetes-sigs/controller-tools to v0.15.0 ([#667](https://github.com/open-feature/open-feature-operator/issues/667)) ([60f528f](https://github.com/open-feature/open-feature-operator/commit/60f528f464141a3c93f15684ca5f7c37213a2b6f))
* **deps:** update docker/metadata-action digest to f7b4ed1 ([#598](https://github.com/open-feature/open-feature-operator/issues/598)) ([28700ce](https://github.com/open-feature/open-feature-operator/commit/28700ce600c74bae921d88ede113313fe9924efb))
* **deps:** update helm/kind-action action to v1.10.0 ([#668](https://github.com/open-feature/open-feature-operator/issues/668)) ([e0b1748](https://github.com/open-feature/open-feature-operator/commit/e0b1748a265a741a17317730dfbb6270f7c43f31))
* **deps:** update open-feature/flagd ([#670](https://github.com/open-feature/open-feature-operator/issues/670)) ([1174a1b](https://github.com/open-feature/open-feature-operator/commit/1174a1b277c1f335b5f73ee76e0c111fd16ace4b))
* release apis 0.2.43 ([#660](https://github.com/open-feature/open-feature-operator/issues/660)) ([aed8ba1](https://github.com/open-feature/open-feature-operator/commit/aed8ba19ffd00f202cdfa980ef063bae49468faa))
## [0.6.0](https://github.com/open-feature/open-feature-operator/compare/v0.5.7...v0.6.0) (2024-05-29)
### ⚠ BREAKING CHANGES
* remove flagdResourceEnabled ([#652](https://github.com/open-feature/open-feature-operator/issues/652))
### 🐛 Bug Fixes
* remove flagdResourceEnabled ([#652](https://github.com/open-feature/open-feature-operator/issues/652)) ([640ff10](https://github.com/open-feature/open-feature-operator/commit/640ff10c5976df1d0fc66251781b8b0cfeff0df0))
## [0.5.7](https://github.com/open-feature/open-feature-operator/compare/v0.5.6...v0.5.7) (2024-05-29)
### 🐛 Bug Fixes
* adapt rolebinding to modified manager role ([#647](https://github.com/open-feature/open-feature-operator/issues/647)) ([e627f11](https://github.com/open-feature/open-feature-operator/commit/e627f112e92bea221fcf40aacdf92eec157ffaea))
* include parameters with default values to envVars ([#648](https://github.com/open-feature/open-feature-operator/issues/648)) ([4f0477c](https://github.com/open-feature/open-feature-operator/commit/4f0477c8e0da571a1cf11e4ac8b57dba3d98efe2))
### 🧹 Chore
* bump k8s libs ([#644](https://github.com/open-feature/open-feature-operator/issues/644)) ([a18d272](https://github.com/open-feature/open-feature-operator/commit/a18d27270eeb9eb7aaccd9e6fb368a55b94f98ba))
* release apis 0.2.42 ([#650](https://github.com/open-feature/open-feature-operator/issues/650)) ([b6cd29f](https://github.com/open-feature/open-feature-operator/commit/b6cd29f787650f6a85f9799fa0c54464dcef58f5))
## [0.5.6](https://github.com/open-feature/open-feature-operator/compare/v0.5.5...v0.5.6) (2024-05-28)
### ✨ New Features
* add `flagd` CRD with ingress support ([#633](https://github.com/open-feature/open-feature-operator/issues/633)) ([b0b99a7](https://github.com/open-feature/open-feature-operator/commit/b0b99a7d101fb7e281394acd0d8b22a16546708f))
* introduce new CRD for in-process evaluation ([#632](https://github.com/open-feature/open-feature-operator/issues/632)) ([51db913](https://github.com/open-feature/open-feature-operator/commit/51db913bc708cc60f00e430e372b68c28c7cbda2))
### 🐛 Bug Fixes
* helm sidecar resources not applied ([#639](https://github.com/open-feature/open-feature-operator/issues/639)) ([d549144](https://github.com/open-feature/open-feature-operator/commit/d54914460b9f01e10bdc958a46ff210fd0f4c374))
* inject env variables to all pod containers ([#634](https://github.com/open-feature/open-feature-operator/issues/634)) ([b21378e](https://github.com/open-feature/open-feature-operator/commit/b21378e4e58b050b36abb8492f6f15be5bca6268))
* use flagd standalone tag instead of sidecar tag for flagd deployments ([#643](https://github.com/open-feature/open-feature-operator/issues/643)) ([a8b7ad4](https://github.com/open-feature/open-feature-operator/commit/a8b7ad49d8364492ffef9c96bfe08c66cfaf6fe3))
### 🧹 Chore
* init workspace before linting ([#638](https://github.com/open-feature/open-feature-operator/issues/638)) ([65e20cf](https://github.com/open-feature/open-feature-operator/commit/65e20cf72b3e1c90e3c3a6ab714fd82c2189cd33))
* release apis 0.2.41 ([#627](https://github.com/open-feature/open-feature-operator/issues/627)) ([546635e](https://github.com/open-feature/open-feature-operator/commit/546635e6d486fd0dbc4aba985e43a928918fd1f4))
### 📚 Documentation
* document new Flagd CRD ([#641](https://github.com/open-feature/open-feature-operator/issues/641)) ([06b399e](https://github.com/open-feature/open-feature-operator/commit/06b399e0cf39bcee3a2804759649e7a28a38a55a))
* support in-process evaluation ([#640](https://github.com/open-feature/open-feature-operator/issues/640)) ([9721825](https://github.com/open-feature/open-feature-operator/commit/972182539ea9ce0440f700456ddeb7d36672a8fb))
## [0.5.5](https://github.com/open-feature/open-feature-operator/compare/v0.5.4...v0.5.5) (2024-05-13)
### ✨ New Features
* introduce validating webhook for FeatureFlag CR ([#622](https://github.com/open-feature/open-feature-operator/issues/622)) ([c4831a3](https://github.com/open-feature/open-feature-operator/commit/c4831a3cdc00aec36f3fe9bec9abceafba1f8aa8))
* operator interval ([#621](https://github.com/open-feature/open-feature-operator/issues/621)) ([bcc5912](https://github.com/open-feature/open-feature-operator/commit/bcc59120423610a37a3e0aec2d6c347f7fed095b))
### 🐛 Bug Fixes
* Add capability to skip crd installation during helm install ([#625](https://github.com/open-feature/open-feature-operator/issues/625)) ([a40e13b](https://github.com/open-feature/open-feature-operator/commit/a40e13b421e7a95c1d4635a87cde8b3203b4571b))
### 🧹 Chore
* bump operator builder tools versions ([#626](https://github.com/open-feature/open-feature-operator/issues/626)) ([918a697](https://github.com/open-feature/open-feature-operator/commit/918a69732fabb34af2f83ca8f650e433e87d0212))
* **deps:** update actions/checkout action to v4 ([#603](https://github.com/open-feature/open-feature-operator/issues/603)) ([4eda2ca](https://github.com/open-feature/open-feature-operator/commit/4eda2ca837c7a8c967d53d4902ed223cbc7e1a6e))
* **deps:** update helm/kind-action action to v1.9.0 ([#608](https://github.com/open-feature/open-feature-operator/issues/608)) ([8800728](https://github.com/open-feature/open-feature-operator/commit/8800728e14998b88a7f2b86977d980a3200e4e1d))
* **deps:** update module golang.org/x/net to v0.24.0 ([#613](https://github.com/open-feature/open-feature-operator/issues/613)) ([b6daece](https://github.com/open-feature/open-feature-operator/commit/b6daece6c4bb6dc42e059fcbef4544cb7825e0c2))
* release apis 0.2.40 ([#620](https://github.com/open-feature/open-feature-operator/issues/620)) ([e39e763](https://github.com/open-feature/open-feature-operator/commit/e39e7638a1cc7985e665229303f18dcb57b4b95a))
* update API to the latest version ([#631](https://github.com/open-feature/open-feature-operator/issues/631)) ([2c39428](https://github.com/open-feature/open-feature-operator/commit/2c394282592bf9f6626c80bdeea2e5e20cabd274))
* use workspaces to make api changes easier ([#635](https://github.com/open-feature/open-feature-operator/issues/635)) ([0479540](https://github.com/open-feature/open-feature-operator/commit/04795403f69d64f85ad53a7e8d0fa5cbc908c169))
### 📚 Documentation
* bump cert manager version ([2e59477](https://github.com/open-feature/open-feature-operator/commit/2e594773444087a109bfccef54a091f23ff7f9c6))
* bump cert manager version ([de2f2b5](https://github.com/open-feature/open-feature-operator/commit/de2f2b59b39911b29cca1b22ffd0c5dd32b32e9b))
## [0.5.4](https://github.com/open-feature/open-feature-operator/compare/v0.5.3...v0.5.4) (2024-02-21)

View File

@ -36,6 +36,9 @@ and deploying to your cluster. Please be aware that it is using the cluster your
Some part of the project docs may be autogenerated and require running a script.
#### Re-generating helm docs after modifying the chart
` ./.github/scripts/generate-helm-docs.sh`
#### CRDs Docs
If you modified or added crds to the project, then you should recreate the crds.md file. To do so run:

View File

@ -1,30 +1,33 @@
# Build the manager binary
FROM --platform=$BUILDPLATFORM golang:1.20.3-alpine3.16 AS builder
FROM --platform=$BUILDPLATFORM golang:1.23.5-alpine3.20 AS builder
WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download
# Copy the go source
COPY main.go main.go
COPY apis/ apis/
COPY webhooks/ webhooks/
COPY controllers/ controllers/
COPY common/ common/
COPY cmd/ cmd/
COPY api/ api/
COPY internal/ internal/
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go work init . ./api && go mod download
ARG TARGETOS
ARG TARGETARCH
# Build
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o manager main.go
# the GOARCH has not a default value to allow the binary be built according to the host where the command
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot as production
FROM gcr.io/distroless/static:nonroot AS production
WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532

View File

@ -6,11 +6,13 @@ ARCH?=amd64
IMG?=$(RELEASE_REGISTRY)/$(RELEASE_IMAGE)
# customize overlay to be used in the build, DEFAULT or HELM
KUSTOMIZE_OVERLAY ?= DEFAULT
CHART_VERSION=v0.5.4# x-release-please-version
CHART_VERSION=v0.8.7# x-release-please-version
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.26.1
WAIT_TIMEOUT_SECONDS?=60
ALL_GO_MOD_DIRS := $(shell find . -type f -name 'go.mod' -exec dirname {} \; | sort)
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
@ -63,8 +65,8 @@ vet: ## Run go vet against code.
go vet ./...
.PHONY: unit-test
unit-test: manifests fmt vet generate envtest ## Run tests.
cd apis && go test ./... -v -coverprofile ../cover-apis.out cover-main.out cover-pkg.out
unit-test: manifests generate envtest fmt vet ## Run tests.
cd api && go test ./... -v -coverprofile ../cover-apis.out cover-main.out cover-pkg.out
go test ./... -v -coverprofile cover-operator.out
sed -i '/mode: set/d' "cover-operator.out"
sed -i '/mode: set/d' "cover-apis.out"
@ -72,14 +74,17 @@ unit-test: manifests fmt vet generate envtest ## Run tests.
cat cover-operator.out cover-apis.out >> cover.out
rm cover-operator.out cover-apis.out
## e2e tests require the operator to be deployed in a real cluster
.PHONY: e2e-test-kuttl
e2e-test-kuttl:
kubectl kuttl test --start-kind=false --config=./kuttl-test.yaml
############
# CHAINSAW #
############
.PHONY: e2e-test-kuttl-local
e2e-test-kuttl-local:
kubectl kuttl test --start-kind=false --config=./kuttl-test-local.yaml
.PHONY: e2e-test-chainsaw #these tests should run on a real cluster!
e2e-test-chainsaw:
chainsaw test --test-dir ./test/e2e/chainsaw
.PHONY: e2e-test-chainsaw-local #these tests should run on a real cluster!
e2e-test-chainsaw-local:
chainsaw test --test-dir ./test/e2e/chainsaw --config ./.chainsaw-local.yaml
.PHONY: e2e-test-validate-local
e2e-test-validate-local:
@ -87,13 +92,13 @@ e2e-test-validate-local:
kind create cluster --config ./test/e2e/kind-cluster.yml --name e2e-tests
kind load docker-image open-feature-operator-local:validate --name e2e-tests
IMG=open-feature-operator-local:validate make deploy-operator
IMG=open-feature-operator-local:validate make e2e-test-kuttl
IMG=open-feature-operator-local:validate make e2e-test-chainsaw
kind delete cluster --name e2e-tests
.PHONY: lint
lint:
go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest
${GOPATH}/bin/golangci-lint run --deadline=3m --timeout=3m --config=./.golangci.yml -v ./... # Run linters
${GOPATH}/bin/golangci-lint run --timeout=3m --config=./.golangci.yml -v ./... # Run linters
.PHONY: generate-crdocs
generate-crdocs: kustomize crdocs
@ -107,12 +112,12 @@ generate-crdocs: kustomize crdocs
##@ Build
.PHONY: build
build: generate fmt vet ## Build manager binary.
go build -o bin/manager main.go
build: manifests generate fmt vet ## Build manager binary.
go build -o bin/manager cmd/main.go
.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./main.go
go run ./cmd/main.go
.PHONY: docker-build
docker-build: clean ## Build docker image with the manager.
@ -169,7 +174,7 @@ undeploy: generate ## Undeploy controller from the K8s cluster specified in ~/.k
.PHONY: deploy-operator
deploy-operator:
kubectl create ns 'open-feature-operator-system' --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml
kubectl wait --for=condition=Available=True deploy --all -n 'cert-manager' --timeout=$(WAIT_TIMEOUT_SECONDS)s
make deploy
kubectl wait --for=condition=Available=True deploy --all -n 'open-feature-operator-system' --timeout=$(WAIT_TIMEOUT_SECONDS)s
@ -204,17 +209,16 @@ CRDOC ?= $(LOCALBIN)/crdoc
## Tool Versions
# renovate: datasource=github-tags depName=kubernetes-sigs/kustomize
KUSTOMIZE_VERSION ?= v4.5.7
KUSTOMIZE_VERSION ?= v5.4.1
# renovate: datasource=github-releases depName=kubernetes-sigs/controller-tools
CONTROLLER_TOOLS_VERSION ?= v0.10.0
CONTROLLER_TOOLS_VERSION ?= v0.16.5
CRDOC_VERSION ?= v0.6.2
KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE): $(LOCALBIN)
[ -e "$(KUSTOMIZE)" ] && rm -rf "$(KUSTOMIZE)" || true
curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN)
test -s ${LOCALBIN}/kustomize || GOBIN=${LOCALBIN} GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION)
.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
@ -245,6 +249,9 @@ set-helm-overlay:
${eval KUSTOMIZE_OVERLAY = HELM}
helm-package: set-helm-overlay generate release-manifests helm
mkdir -p chart/open-feature-operator/templates/crds
mv chart/open-feature-operator/templates/*customresourcedefinition* chart/open-feature-operator/templates/crds
.github/scripts/strip-kustomize-helm.sh
$(HELM) package --version $(CHART_VERSION) chart/open-feature-operator
mkdir -p charts && mv open-feature-operator-*.tgz charts
$(HELM) repo index --url https://open-feature.github.io/open-feature-operator/charts charts
@ -253,4 +260,16 @@ helm-package: set-helm-overlay generate release-manifests helm
install-mockgen:
go install github.com/golang/mock/mockgen@v1.6.0
mockgen: install-mockgen
mockgen -source=controllers/common/flagd-injector.go -destination=controllers/common/mock/flagd-injector.go -package=commonmock
mockgen -source=./common/flagdinjector/flagdinjector.go -destination=./common/flagdinjector/mock/flagd-injector.go -package=commonmock
mockgen -source=./controllers/core/flagd/controller.go -destination=controllers/core/flagd/mock/mock.go -package=commonmock
mockgen -source=./controllers/core/flagd/resources/interface.go -destination=controllers/core/flagd/resources/mock/mock.go -package=commonmock
workspace-init: workspace-clean
go work init
$(foreach module, $(ALL_GO_MOD_DIRS), go work use $(module);)
workspace-update:
$(foreach module, $(ALL_GO_MOD_DIRS), go work use $(module);)
workspace-clean:
rm -rf go.work

28
PROJECT
View File

@ -1,7 +1,13 @@
# Code generated by tool. DO NOT EDIT.
# This file is used to track the info used to scaffold your project
# and allow the plugins properly work.
# More info: https://book.kubebuilder.io/reference/project-config.html
domain: openfeature.dev
layout:
- go.kubebuilder.io/v3
- go.kubebuilder.io/v4
multigroup: true
plugins:
helm.kubebuilder.io/v1-alpha: {}
projectName: open-feature-operator
repo: github.com/open-feature/open-feature-operator
resources:
@ -51,6 +57,9 @@ resources:
kind: FeatureFlag
path: github.com/open-feature/open-feature-operator/apis/core/v1beta1
version: v1beta1
webhooks:
validation: true
webhookVersion: v1
- api:
crdVersion: v1
namespaced: true
@ -59,4 +68,21 @@ resources:
kind: FeatureFlagSource
path: github.com/open-feature/open-feature-operator/apis/core/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
controller: true
domain: openfeature.dev
group: core
kind: Flagd
path: github.com/open-feature/open-feature-operator/apis/core/v1beta1
version: v1beta1
- api:
crdVersion: v1
namespaced: true
domain: openfeature.dev
group: core
kind: InProcessConfiguration
path: github.com/open-feature/open-feature-operator/apis/core/v1beta1
version: v1beta1
version: "3"

View File

@ -33,7 +33,8 @@ See [CHANGELOG.md](https://github.com/open-feature/open-feature-operator/blob/ma
See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to the OpenFeature project.
Our community meetings are held regularly and open to everyone. Check the [OpenFeature community calendar](https://calendar.google.com/calendar/u/0?cid=MHVhN2kxaGl2NWRoMThiMjd0b2FoNjM2NDRAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ) for specific dates and for the Zoom meeting links.
Our community meetings are held regularly and open to everyone, as well as other community channels.
Check the [OpenFeature community page]https://openfeature.dev/community/) for the links and participation guidelines.
Thanks so much to our contributors.

View File

@ -1,5 +1,72 @@
# Changelog
## [0.2.45](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.44...apis/v0.2.45) (2025-01-13)
### ✨ New Features
* add gateway api support ([#725](https://github.com/open-feature/open-feature-operator/issues/725)) ([b393a26](https://github.com/open-feature/open-feature-operator/commit/b393a2669c05d58afe453867401f8d697464b145))
### 🐛 Bug Fixes
* flagd environment variables missing prefix ([#730](https://github.com/open-feature/open-feature-operator/issues/730)) ([0aa61ec](https://github.com/open-feature/open-feature-operator/commit/0aa61ec1419ec1d99f3c875dd6526ec8ca8e6014))
## [0.2.44](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.43...apis/v0.2.44) (2024-07-23)
### 🐛 Bug Fixes
* **deps:** update module github.com/stretchr/testify to v1.9.0 ([#671](https://github.com/open-feature/open-feature-operator/issues/671)) ([1d2713d](https://github.com/open-feature/open-feature-operator/commit/1d2713dad6381e56aa3b552c33e1cb3513574a6e))
### 🧹 Chore
* **deps:** update open-feature/flagd ([#689](https://github.com/open-feature/open-feature-operator/issues/689)) ([0d331a9](https://github.com/open-feature/open-feature-operator/commit/0d331a9bc5db752cb3aa49f7ce5afc0830f115fe))
## [0.2.43](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.42...apis/v0.2.43) (2024-06-06)
### 🐛 Bug Fixes
* flagd path defaults ([#658](https://github.com/open-feature/open-feature-operator/issues/658)) ([aef1010](https://github.com/open-feature/open-feature-operator/commit/aef1010dff162e8d232942e642c68e3e9ba3f35f))
### 🧹 Chore
* **deps:** update open-feature/flagd ([#670](https://github.com/open-feature/open-feature-operator/issues/670)) ([1174a1b](https://github.com/open-feature/open-feature-operator/commit/1174a1b277c1f335b5f73ee76e0c111fd16ace4b))
### 📚 Documentation
* require hosts, mention host-less rules ([#659](https://github.com/open-feature/open-feature-operator/issues/659)) ([dcab14a](https://github.com/open-feature/open-feature-operator/commit/dcab14a2c55ada5f1df34b3ed164c8b334877b68))
## [0.2.42](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.41...apis/v0.2.42) (2024-05-29)
### 🐛 Bug Fixes
* include parameters with default values to envVars ([#648](https://github.com/open-feature/open-feature-operator/issues/648)) ([4f0477c](https://github.com/open-feature/open-feature-operator/commit/4f0477c8e0da571a1cf11e4ac8b57dba3d98efe2))
### 🧹 Chore
* bump k8s libs ([#644](https://github.com/open-feature/open-feature-operator/issues/644)) ([a18d272](https://github.com/open-feature/open-feature-operator/commit/a18d27270eeb9eb7aaccd9e6fb368a55b94f98ba))
## [0.2.41](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.40...apis/v0.2.41) (2024-05-28)
### ✨ New Features
* add `flagd` CRD with ingress support ([#633](https://github.com/open-feature/open-feature-operator/issues/633)) ([b0b99a7](https://github.com/open-feature/open-feature-operator/commit/b0b99a7d101fb7e281394acd0d8b22a16546708f))
* introduce new CRD for in-process evaluation ([#632](https://github.com/open-feature/open-feature-operator/issues/632)) ([51db913](https://github.com/open-feature/open-feature-operator/commit/51db913bc708cc60f00e430e372b68c28c7cbda2))
* introduce validating webhook for FeatureFlag CR ([#622](https://github.com/open-feature/open-feature-operator/issues/622)) ([c4831a3](https://github.com/open-feature/open-feature-operator/commit/c4831a3cdc00aec36f3fe9bec9abceafba1f8aa8))
### 🧹 Chore
* bump operator builder tools versions ([#626](https://github.com/open-feature/open-feature-operator/issues/626)) ([918a697](https://github.com/open-feature/open-feature-operator/commit/918a69732fabb34af2f83ca8f650e433e87d0212))
## [0.2.40](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.39...apis/v0.2.40) (2024-04-22)

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022.

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022.

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022.

View File

@ -0,0 +1,131 @@
package common
import (
"fmt"
corev1 "k8s.io/api/core/v1"
)
type SyncProviderType string
const (
SyncProviderKubernetes SyncProviderType = "kubernetes"
SyncProviderFilepath SyncProviderType = "file"
SyncProviderGcs SyncProviderType = "gcs"
SyncProviderHttp SyncProviderType = "http"
SyncProviderGrpc SyncProviderType = "grpc"
SyncProviderFlagdProxy SyncProviderType = "flagd-proxy"
)
const (
ManagementPortEnvVar string = "MANAGEMENT_PORT"
PortEnvVar string = "PORT"
HostEnvVar string = "HOST"
TLSEnvVar string = "TLS"
SocketPathEnvVar string = "SOCKET_PATH"
OfflineFlagSourcePathEnvVar string = "OFFLINE_FLAG_SOURCE_PATH"
SelectorEnvVar string = "SOURCE_SELECTOR"
CacheEnvVar string = "CACHE"
CacheMaxSizeEnvVar string = "MAX_CACHE_SIZE"
ResolverEnvVar string = "RESOLVER"
EvaluatorEnvVar string = "EVALUATOR"
ImageEnvVar string = "IMAGE"
VersionEnvVar string = "TAG"
ProviderArgsEnvVar string = "PROVIDER_ARGS"
DefaultSyncProviderEnvVar string = "SYNC_PROVIDER"
LogFormatEnvVar string = "LOG_FORMAT"
ProbesEnabledVar string = "PROBES_ENABLED"
DefaultEnvVarPrefix string = "FLAGD"
DefaultManagementPort int32 = 8014
DefaultRPCPort int32 = 8013
DefaultInProcessPort int32 = 8015
DefaultEvaluator string = "json"
DefaultLogFormat string = "json"
DefaultProbesEnabled bool = true
DefaultTLS bool = false
DefaultHost string = "localhost"
DefaultCache string = "lru"
DefaultCacheMaxSize int32 = 1000
InProcessResolverType string = "in-process"
RPCResolverType string = "rpc"
)
func (s SyncProviderType) IsKubernetes() bool {
return s == SyncProviderKubernetes
}
func (s SyncProviderType) IsHttp() bool {
return s == SyncProviderHttp
}
func (s SyncProviderType) IsGcs() bool {
return s == SyncProviderGcs
}
func (s SyncProviderType) IsFilepath() bool {
return s == SyncProviderFilepath
}
func (s SyncProviderType) IsGrpc() bool {
return s == SyncProviderGrpc
}
func (s SyncProviderType) IsFlagdProxy() bool {
return s == SyncProviderFlagdProxy
}
func TrueVal() *bool {
b := true
return &b
}
func FalseVal() *bool {
b := false
return &b
}
func EnvVarKey(prefix string, suffix string) string {
return fmt.Sprintf("%s_%s", prefix, suffix)
}
// unique string used to create unique volume mount and file name
func FeatureFlagConfigurationId(namespace, name string) string {
return EnvVarKey(namespace, name)
}
// unique key (and filename) for configMap data
func FeatureFlagConfigMapKey(namespace, name string) string {
return fmt.Sprintf("%s.flagd.json", FeatureFlagConfigurationId(namespace, name))
}
func RemoveDuplicateEnvVars(input []corev1.EnvVar) []corev1.EnvVar {
out := make([]corev1.EnvVar, 0, len(input))
for i := len(input) - 1; i >= 0; i-- {
if !isEnvVarNamePresent(out, input[i]) {
out = append(out, input[i])
}
}
return out
}
func isEnvVarNamePresent(slice []corev1.EnvVar, item corev1.EnvVar) bool {
for _, i := range slice {
if i.Name == item.Name {
return true
}
}
return false
}
func RemoveDuplicatesFromSlice[T comparable](input []T) []T {
seen := make(map[T]bool)
result := []T{}
for _, item := range input {
if _, ok := seen[item]; !ok {
seen[item] = true
result = append(result, item)
}
}
return result
}

View File

@ -0,0 +1,151 @@
package common
import (
"testing"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
)
func Test_FeatureFlagSource_SyncProvider(t *testing.T) {
k := SyncProviderKubernetes
f := SyncProviderFilepath
h := SyncProviderHttp
g := SyncProviderGrpc
gcs := SyncProviderGcs
require.True(t, k.IsKubernetes())
require.True(t, f.IsFilepath())
require.True(t, h.IsHttp())
require.True(t, g.IsGrpc())
require.True(t, gcs.IsGcs())
require.False(t, f.IsKubernetes())
require.False(t, h.IsFilepath())
require.False(t, k.IsGrpc())
require.False(t, g.IsHttp())
require.False(t, g.IsGcs())
}
func Test_FLagSourceConfiguration_EnvVarKey(t *testing.T) {
require.Equal(t, "pre_suf", EnvVarKey("pre", "suf"))
}
func Test_FLagSourceConfiguration_FeatureFlagConfigurationId(t *testing.T) {
require.Equal(t, "pre_suf", FeatureFlagConfigurationId("pre", "suf"))
}
func Test_FLagSourceConfiguration_FeatureFlagConfigMapKey(t *testing.T) {
require.Equal(t, "pre_suf.flagd.json", FeatureFlagConfigMapKey("pre", "suf"))
}
func Test_RemoveDuplicateEnvVars(t *testing.T) {
input1 := []corev1.EnvVar{
{
Name: "key1",
Value: "val1",
},
{
Name: "key2",
Value: "val2",
},
{
Name: "key1",
Value: "val3",
},
}
input2 := []corev1.EnvVar{
{
Name: "key1",
Value: "val1",
},
{
Name: "key2",
Value: "val2",
},
{
Name: "key3",
Value: "val3",
},
}
input3 := []corev1.EnvVar{
{
Name: "key1",
Value: "val1",
},
{
Name: "key2",
Value: "val2",
},
{
Name: "key1",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "secret",
},
},
},
},
}
out1 := RemoveDuplicateEnvVars(input1)
require.Len(t, out1, 2)
require.Contains(t, out1, corev1.EnvVar{
Name: "key1",
Value: "val3",
})
require.Contains(t, out1, corev1.EnvVar{
Name: "key2",
Value: "val2",
})
out2 := RemoveDuplicateEnvVars(input2)
require.Len(t, out2, 3)
require.Contains(t, out2, corev1.EnvVar{
Name: "key1",
Value: "val1",
})
require.Contains(t, out2, corev1.EnvVar{
Name: "key2",
Value: "val2",
})
require.Contains(t, out2, corev1.EnvVar{
Name: "key3",
Value: "val3",
})
out3 := RemoveDuplicateEnvVars(input3)
require.Len(t, out3, 2)
require.Contains(t, out3, corev1.EnvVar{
Name: "key1",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "secret",
},
},
},
})
require.Contains(t, out3, corev1.EnvVar{
Name: "key2",
Value: "val2",
})
}
func Test_RRemoveDuplicatesFromSlice(t *testing.T) {
input1 := []string{
"some", "input", "duplicate", "some",
}
input2 := []int{
1, 2, 3, 4, 2,
}
require.Equal(t, RemoveDuplicatesFromSlice(input1), []string{
"some", "input", "duplicate",
})
require.Equal(t, RemoveDuplicatesFromSlice(input2), []int{
1, 2, 3, 4,
})
}

View File

@ -31,7 +31,7 @@ type FeatureFlagSpec struct {
}
type FlagSpec struct {
Flags map[string]Flag `json:"flags"`
Flags `json:",inline"`
// +optional
// +kubebuilder:validation:Schemaless
// +kubebuilder:pruning:PreserveUnknownFields
@ -39,6 +39,11 @@ type FlagSpec struct {
Evaluators json.RawMessage `json:"$evaluators,omitempty"`
}
// Flags represent the flags specification
type Flags struct {
FlagsMap map[string]Flag `json:"flags"`
}
type Flag struct {
// +kubebuilder:validation:Enum=ENABLED;DISABLED
State string `json:"state"`

View File

@ -27,7 +27,7 @@ func Test_FeatureFlag(t *testing.T) {
},
Spec: FeatureFlagSpec{
FlagSpec: FlagSpec{
Flags: map[string]Flag{},
Flags: Flags{},
},
},
}
@ -64,7 +64,7 @@ func Test_FeatureFlag(t *testing.T) {
OwnerReferences: references,
},
Data: map[string]string{
"cmnamespace_cmname.flagd.json": "{\"flags\":{}}",
"cmnamespace_cmname.flagd.json": "{\"flags\":null}",
},
}, *cm)
}

View File

@ -24,36 +24,16 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
const (
SidecarEnvVarPrefix string = "SIDECAR_ENV_VAR_PREFIX"
InputConfigurationEnvVarPrefix string = "SIDECAR"
SidecarMetricPortEnvVar string = "MANAGEMENT_PORT"
SidecarPortEnvVar string = "PORT"
SidecarSocketPathEnvVar string = "SOCKET_PATH"
SidecarEvaluatorEnvVar string = "EVALUATOR"
SidecarImageEnvVar string = "IMAGE"
SidecarVersionEnvVar string = "TAG"
SidecarProviderArgsEnvVar string = "PROVIDER_ARGS"
SidecarDefaultSyncProviderEnvVar string = "SYNC_PROVIDER"
SidecarLogFormatEnvVar string = "LOG_FORMAT"
SidecarProbesEnabledVar string = "PROBES_ENABLED"
defaultSidecarEnvVarPrefix string = "FLAGD"
DefaultManagementPort int32 = 8014
defaultPort int32 = 8013
defaultSocketPath string = ""
defaultEvaluator string = "json"
defaultLogFormat string = "json"
defaultProbesEnabled bool = true
)
// FeatureFlagSourceSpec defines the desired state of FeatureFlagSource
type FeatureFlagSourceSpec struct {
// ManagemetPort defines the port to serve management on, defaults to 8014
// +optional
// +kubebuilder:default:=8014
ManagementPort int32 `json:"managementPort"`
// Port defines the port to listen on, defaults to 8013
// +optional
// +kubebuilder:default:=8013
Port int32 `json:"port"`
// SocketPath defines the unix socket path to listen on
@ -62,6 +42,7 @@ type FeatureFlagSourceSpec struct {
// Evaluator sets an evaluator, defaults to 'json'
// +optional
// +kubebuilder:default:="json"
Evaluator string `json:"evaluator"`
// SyncProviders define the syncProviders and associated configuration to be applied to the sidecar
@ -83,10 +64,12 @@ type FeatureFlagSourceSpec struct {
// LogFormat allows for the sidecar log format to be overridden, defaults to 'json'
// +optional
// +kubebuilder:default:="json"
LogFormat string `json:"logFormat"`
// EnvVarPrefix defines the prefix to be applied to all environment variables applied to the sidecar, default FLAGD
// +optional
// +kubebuilder:default:="FLAGD"
EnvVarPrefix string `json:"envVarPrefix"`
// RolloutOnChange dictates whether annotated deployments will be restarted when configuration changes are
@ -197,9 +180,11 @@ func (fc *FeatureFlagSourceSpec) Merge(new *FeatureFlagSourceSpec) {
}
if len(new.EnvVars) != 0 {
fc.EnvVars = append(fc.EnvVars, new.EnvVars...)
fc.EnvVars = common.RemoveDuplicateEnvVars(fc.EnvVars)
}
if len(new.SyncProviderArgs) != 0 {
fc.SyncProviderArgs = append(fc.SyncProviderArgs, new.SyncProviderArgs...)
fc.SyncProviderArgs = common.RemoveDuplicatesFromSlice[string](fc.SyncProviderArgs)
}
if new.EnvVarPrefix != "" {
fc.EnvVarPrefix = new.EnvVarPrefix
@ -234,40 +219,39 @@ func (fc *FeatureFlagSourceSpec) ToEnvVars() []corev1.EnvVar {
})
}
if fc.ManagementPort != DefaultManagementPort {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, SidecarMetricPortEnvVar),
Value: fmt.Sprintf("%d", fc.ManagementPort),
})
}
// default values are always included in the envVars
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.ManagementPortEnvVar),
Value: fmt.Sprintf("%d", fc.ManagementPort),
})
if fc.Port != defaultPort {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, SidecarPortEnvVar),
Value: fmt.Sprintf("%d", fc.Port),
})
}
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.PortEnvVar),
Value: fmt.Sprintf("%d", fc.Port),
})
if fc.Evaluator != defaultEvaluator {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, SidecarEvaluatorEnvVar),
Value: fc.Evaluator,
})
}
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.EvaluatorEnvVar),
Value: fc.Evaluator,
})
if fc.SocketPath != defaultSocketPath {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.LogFormatEnvVar),
Value: fc.LogFormat,
})
// sets the FLAGD_RESOLVER var to "rpc" to configure the provider for RPC evaluation mode
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.ResolverEnvVar),
Value: common.RPCResolverType,
})
if fc.SocketPath != "" {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, SidecarSocketPathEnvVar),
Name: common.EnvVarKey(fc.EnvVarPrefix, common.SocketPathEnvVar),
Value: fc.SocketPath,
})
}
if fc.LogFormat != defaultLogFormat {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, SidecarLogFormatEnvVar),
Value: fc.LogFormat,
})
}
return envs
}

View File

@ -122,55 +122,50 @@ func Test_FLagSourceConfiguration_Merge(t *testing.T) {
ff_old.Spec.Merge(&ff_new.Spec)
require.Equal(t, &FeatureFlagSource{
Spec: FeatureFlagSourceSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
{
Name: "env3",
Value: "val3",
},
{
Name: "env4",
Value: "val4",
},
},
EnvVarPrefix: "PREFIX",
ManagementPort: 221,
Port: 331,
Evaluator: "evaluator1",
SocketPath: "socket-path1",
LogFormat: "log1",
Sources: []Source{
{
Source: "src1",
Provider: common.SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
Interval: 5,
},
{
Source: "src2",
Provider: common.SyncProviderFilepath,
},
},
SyncProviderArgs: []string{"arg1", "arg2", "arg3", "arg4"},
DefaultSyncProvider: common.SyncProviderFilepath,
RolloutOnChange: common.FalseVal(),
ProbesEnabled: common.FalseVal(),
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
require.Equal(t, ff_old.Spec.EnvVarPrefix, "PREFIX")
require.Equal(t, ff_old.Spec.Port, int32(331))
require.Equal(t, ff_old.Spec.ManagementPort, int32(221))
require.Equal(t, ff_old.Spec.SocketPath, "socket-path1")
require.Equal(t, ff_old.Spec.Evaluator, "evaluator1")
require.Equal(t, ff_old.Spec.LogFormat, "log1")
require.Equal(t, ff_old.Spec.Sources, []Source{
{
Source: "src1",
Provider: common.SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
Interval: 5,
},
}, ff_old)
{
Source: "src2",
Provider: common.SyncProviderFilepath,
},
})
require.Equal(t, ff_old.Spec.SyncProviderArgs, []string{"arg1", "arg2", "arg3", "arg4"})
require.Equal(t, ff_old.Spec.DefaultSyncProvider, common.SyncProviderFilepath)
require.Equal(t, ff_old.Spec.RolloutOnChange, common.FalseVal())
require.Equal(t, ff_old.Spec.ProbesEnabled, common.FalseVal())
require.Equal(t, ff_old.Spec.DebugLogging, common.FalseVal())
require.Equal(t, ff_old.Spec.OtelCollectorUri, "")
require.Len(t, ff_old.Spec.EnvVars, 4)
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env1",
Value: "val1",
})
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env2",
Value: "val2",
})
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env3",
Value: "val3",
})
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env4",
Value: "val4",
})
}
func Test_FLagSourceConfiguration_ToEnvVars(t *testing.T) {
@ -215,14 +210,18 @@ func Test_FLagSourceConfiguration_ToEnvVars(t *testing.T) {
Name: "PRE_EVALUATOR",
Value: "evaluator",
},
{
Name: "PRE_SOCKET_PATH",
Value: "socket-path",
},
{
Name: "PRE_LOG_FORMAT",
Value: "log",
},
{
Name: "PRE_RESOLVER",
Value: "rpc",
},
{
Name: "PRE_SOCKET_PATH",
Value: "socket-path",
},
}
require.Equal(t, expected, ff.Spec.ToEnvVars())
}

View File

@ -0,0 +1,145 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
v1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
gatewayApiv1 "sigs.k8s.io/gateway-api/apis/v1"
)
// FlagdSpec defines the desired state of Flagd
type FlagdSpec struct {
// Replicas defines the number of replicas to create for the service.
// Default: 1
// +optional
// +kubebuilder:default=1
Replicas *int32 `json:"replicas,omitempty"`
// ServiceType represents the type of Service to create.
// Must be one of: ClusterIP, NodePort, LoadBalancer, and ExternalName.
// Default: ClusterIP
// +optional
// +kubebuilder:default=ClusterIP
// +kubebuilder:validation:Enum:=ClusterIP;NodePort;LoadBalancer;ExternalName
ServiceType v1.ServiceType `json:"serviceType,omitempty"`
// ServiceAccountName the service account name for the flagd deployment
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty"`
// FeatureFlagSource references to a FeatureFlagSource from which the created flagd instance retrieves
// the feature flag configurations
FeatureFlagSource string `json:"featureFlagSource"`
// Ingress
// +optional
Ingress IngressSpec `json:"ingress"`
// GatewayApiRoutes
// +optional
GatewayApiRoutes GatewayApiSpec `json:"gatewayApiRoutes"`
}
// IngressSpec defines the options to be used when deploying the ingress for flagd
type IngressSpec struct {
// Enabled enables/disables the ingress for flagd
Enabled bool `json:"enabled,omitempty"`
// Annotations the annotations to be added to the ingress
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
// Hosts list of hosts to be added to the ingress.
// Empty string corresponds to rule with no host.
Hosts []string `json:"hosts"`
// TLS configuration for the ingress
TLS []networkingv1.IngressTLS `json:"tls,omitempty"`
// IngressClassName defines the name if the ingress class to be used for flagd
// +optional
IngressClassName *string `json:"ingressClassName,omitempty"`
// PathType is the path type to be used for the ingress rules
// +optional
PathType networkingv1.PathType `json:"pathType,omitempty"`
// FlagdPath is the path to be used for accessing the flagd flag evaluation API
// Default: /flagd.evaluation.v1.Service
// +optional
FlagdPath string `json:"flagdPath,omitempty"`
// OFREPPath is the path to be used for accessing the OFREP API
// Default: /ofrep
// +optional
OFREPPath string `json:"ofrepPath,omitempty"`
// SyncPath is the path to be used for accessing the sync API
// Default: /flagd.sync.v1.Service
// +optional
SyncPath string `json:"syncPath,omitempty"`
}
// GatewayApiSpec defines the options to be used when deploying Gateway API routes for flagd
type GatewayApiSpec struct {
// Enabled enables/disables the Gateway API routes for flagd
Enabled bool `json:"enabled,omitempty"`
// Annotations to be added to the Gateway API routes
// +optional
Annotations map[string]string `json:"annotations,omitempty"`
// Hosts list of hosts to be added to the ingress.
// Empty string corresponds to rule with no host.
// +optional
Hosts []string `json:"hosts,omitempty"`
// ParentRefs references the resources (usually Gateways) that the Routes should
// be attached to.
ParentRefs []gatewayApiv1.ParentReference `json:"parentRefs"`
}
// FlagdStatus defines the observed state of Flagd
type FlagdStatus struct {
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// Flagd is the Schema for the flagds API
type Flagd struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec FlagdSpec `json:"spec,omitempty"`
Status FlagdStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// FlagdList contains a list of Flagd
type FlagdList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Flagd `json:"items"`
}
func init() {
SchemeBuilder.Register(&Flagd{}, &FlagdList{})
}

View File

@ -0,0 +1,209 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
import (
"fmt"
"github.com/open-feature/open-feature-operator/apis/core/v1beta1/common"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// InProcessConfigurationSpec defines the desired state of InProcessConfiguration
type InProcessConfigurationSpec struct {
// Port defines the port to listen on, defaults to 8015
// +kubebuilder:default:=8015
// +optional
Port int32 `json:"port"`
// SocketPath defines the unix socket path to listen on
// +optional
SocketPath string `json:"socketPath"`
// Host
// +kubebuilder:default:=localhost
// +optional
Host string `json:"host"`
// TLS
// +kubebuilder:default:=false
// +optional
TLS bool `json:"tls"`
// OfflineFlagSourcePath
// +optional
OfflineFlagSourcePath string `json:"offlineFlagSourcePath"`
// Selector
// +optional
Selector string `json:"selector"`
// Cache
// +kubebuilder:default:="lru"
// +kubebuilder:validation:Pattern="^(lru|disabled)$"
// +kubebuilder:validation:Type:=string
// +optional
Cache string `json:"cache"`
// CacheMaxSize
// +kubebuilder:default:=1000
// +optional
CacheMaxSize int `json:"cacheMaxSize"`
// EnvVars
// +optional
EnvVars []corev1.EnvVar `json:"envVars"`
// EnvVarPrefix defines the prefix to be applied to all environment variables applied to the sidecar, default FLAGD
// +optional
// +kubebuilder:default:=FLAGD
EnvVarPrefix string `json:"envVarPrefix"`
}
// InProcessConfigurationStatus defines the observed state of InProcessConfiguration
type InProcessConfigurationStatus struct {
}
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// InProcessConfiguration is the Schema for the inprocesconfigurations API
type InProcessConfiguration struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec InProcessConfigurationSpec `json:"spec,omitempty"`
Status InProcessConfigurationStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// InProcessConfigurationList contains a list of InProcessConfiguration
type InProcessConfigurationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []InProcessConfiguration `json:"items"`
}
func init() {
SchemeBuilder.Register(&InProcessConfiguration{}, &InProcessConfigurationList{})
}
func (fc *InProcessConfigurationSpec) Merge(new *InProcessConfigurationSpec) {
if new == nil {
return
}
if len(new.EnvVars) != 0 {
fc.EnvVars = append(fc.EnvVars, new.EnvVars...)
fc.EnvVars = common.RemoveDuplicateEnvVars(fc.EnvVars)
}
if new.Port != common.DefaultInProcessPort {
fc.Port = new.Port
}
if new.SocketPath != "" {
fc.SocketPath = new.SocketPath
}
if new.Host != common.DefaultHost {
fc.Host = new.Host
}
if new.EnvVarPrefix != common.DefaultEnvVarPrefix {
fc.EnvVarPrefix = new.EnvVarPrefix
}
if new.OfflineFlagSourcePath != "" {
fc.OfflineFlagSourcePath = new.OfflineFlagSourcePath
}
if new.Selector != "" {
fc.Selector = new.Selector
}
if new.Cache != common.DefaultCache {
fc.Cache = new.Cache
}
if new.CacheMaxSize != int(common.DefaultCacheMaxSize) {
fc.CacheMaxSize = new.CacheMaxSize
}
if new.TLS != common.DefaultTLS {
fc.TLS = new.TLS
}
}
func (fc *InProcessConfigurationSpec) ToEnvVars() []corev1.EnvVar {
envs := []corev1.EnvVar{}
for _, envVar := range fc.EnvVars {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, envVar.Name),
Value: envVar.Value,
})
}
// default values are always included in the envVars
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.HostEnvVar),
Value: fc.Host,
})
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.PortEnvVar),
Value: fmt.Sprintf("%d", fc.Port),
})
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.TLSEnvVar),
Value: fmt.Sprintf("%t", fc.TLS),
})
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.CacheEnvVar),
Value: fc.Cache,
})
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.CacheMaxSizeEnvVar),
Value: fmt.Sprintf("%d", fc.CacheMaxSize),
})
// sets the FLAGD_RESOLVER var to "in-process" to configure the provider for in-process evaluation mode
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.ResolverEnvVar),
Value: common.InProcessResolverType,
})
if fc.SocketPath != "" {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.SocketPathEnvVar),
Value: fc.SocketPath,
})
}
if fc.OfflineFlagSourcePath != "" {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.OfflineFlagSourcePathEnvVar),
Value: fc.OfflineFlagSourcePath,
})
}
if fc.Selector != "" {
envs = append(envs, corev1.EnvVar{
Name: common.EnvVarKey(fc.EnvVarPrefix, common.SelectorEnvVar),
Value: fc.Selector,
})
}
return envs
}

View File

@ -0,0 +1,178 @@
package v1beta1
import (
"testing"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
)
func Test_InProcessConfiguration_Merge(t *testing.T) {
ff_old := &InProcessConfiguration{
Spec: InProcessConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
Port: 33,
SocketPath: "socket-path",
Host: "host",
TLS: true,
OfflineFlagSourcePath: "path1",
Selector: "selector",
Cache: "cache",
CacheMaxSize: 12,
},
}
ff_old.Spec.Merge(nil)
require.Equal(t, &InProcessConfiguration{
Spec: InProcessConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
Port: 33,
SocketPath: "socket-path",
Host: "host",
TLS: true,
OfflineFlagSourcePath: "path1",
Selector: "selector",
Cache: "cache",
CacheMaxSize: 12,
},
}, ff_old)
ff_new := &InProcessConfiguration{
Spec: InProcessConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env3",
Value: "val3",
},
},
EnvVarPrefix: "PRE_SECOND",
Port: 33,
SocketPath: "",
Host: "host",
TLS: true,
OfflineFlagSourcePath: "",
Selector: "",
Cache: "lru",
CacheMaxSize: 1000,
},
}
ff_old.Spec.Merge(&ff_new.Spec)
require.Equal(t, ff_old.Spec.EnvVarPrefix, "PRE_SECOND")
require.Equal(t, ff_old.Spec.Port, int32(33))
require.Equal(t, ff_old.Spec.SocketPath, "socket-path")
require.Equal(t, ff_old.Spec.Host, "host")
require.Equal(t, ff_old.Spec.TLS, true)
require.Equal(t, ff_old.Spec.OfflineFlagSourcePath, "path1")
require.Equal(t, ff_old.Spec.Selector, "selector")
require.Equal(t, ff_old.Spec.Cache, "cache")
require.Equal(t, ff_old.Spec.CacheMaxSize, 12)
require.Len(t, ff_old.Spec.EnvVars, 3)
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env1",
Value: "val1",
})
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env2",
Value: "val2",
})
require.Contains(t, ff_old.Spec.EnvVars, v1.EnvVar{
Name: "env3",
Value: "val3",
})
}
func Test_InProcessConfiguration_ToEnvVars(t *testing.T) {
ff := InProcessConfiguration{
Spec: InProcessConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
Port: 33,
SocketPath: "socket-path",
Host: "host",
TLS: true,
OfflineFlagSourcePath: "path1",
Selector: "selector",
Cache: "cache",
CacheMaxSize: 12,
},
}
expected := []v1.EnvVar{
{
Name: "PRE_env1",
Value: "val1",
},
{
Name: "PRE_env2",
Value: "val2",
},
{
Name: "PRE_HOST",
Value: "host",
},
{
Name: "PRE_PORT",
Value: "33",
},
{
Name: "PRE_TLS",
Value: "true",
},
{
Name: "PRE_CACHE",
Value: "cache",
},
{
Name: "PRE_MAX_CACHE_SIZE",
Value: "12",
},
{
Name: "PRE_RESOLVER",
Value: "in-process",
},
{
Name: "PRE_SOCKET_PATH",
Value: "socket-path",
},
{
Name: "PRE_OFFLINE_FLAG_SOURCE_PATH",
Value: "path1",
},
{
Name: "PRE_SOURCE_SELECTOR",
Value: "selector",
},
}
require.Equal(t, expected, ff.Spec.ToEnvVars())
}

View File

@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2022.
@ -24,7 +23,9 @@ package v1beta1
import (
"encoding/json"
"k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
apisv1 "sigs.k8s.io/gateway-api/apis/v1"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
@ -267,13 +268,7 @@ func (in *Flag) DeepCopy() *Flag {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FlagSpec) DeepCopyInto(out *FlagSpec) {
*out = *in
if in.Flags != nil {
in, out := &in.Flags, &out.Flags
*out = make(map[string]Flag, len(*in))
for key, val := range *in {
(*out)[key] = *val.DeepCopy()
}
}
in.Flags.DeepCopyInto(&out.Flags)
if in.Evaluators != nil {
in, out := &in.Evaluators, &out.Evaluators
*out = make(json.RawMessage, len(*in))
@ -291,6 +286,293 @@ func (in *FlagSpec) DeepCopy() *FlagSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Flagd) DeepCopyInto(out *Flagd) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flagd.
func (in *Flagd) DeepCopy() *Flagd {
if in == nil {
return nil
}
out := new(Flagd)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Flagd) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FlagdList) DeepCopyInto(out *FlagdList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Flagd, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlagdList.
func (in *FlagdList) DeepCopy() *FlagdList {
if in == nil {
return nil
}
out := new(FlagdList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FlagdList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FlagdSpec) DeepCopyInto(out *FlagdSpec) {
*out = *in
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int32)
**out = **in
}
in.Ingress.DeepCopyInto(&out.Ingress)
in.GatewayApiRoutes.DeepCopyInto(&out.GatewayApiRoutes)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlagdSpec.
func (in *FlagdSpec) DeepCopy() *FlagdSpec {
if in == nil {
return nil
}
out := new(FlagdSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FlagdStatus) DeepCopyInto(out *FlagdStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FlagdStatus.
func (in *FlagdStatus) DeepCopy() *FlagdStatus {
if in == nil {
return nil
}
out := new(FlagdStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Flags) DeepCopyInto(out *Flags) {
*out = *in
if in.FlagsMap != nil {
in, out := &in.FlagsMap, &out.FlagsMap
*out = make(map[string]Flag, len(*in))
for key, val := range *in {
(*out)[key] = *val.DeepCopy()
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flags.
func (in *Flags) DeepCopy() *Flags {
if in == nil {
return nil
}
out := new(Flags)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GatewayApiSpec) DeepCopyInto(out *GatewayApiSpec) {
*out = *in
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Hosts != nil {
in, out := &in.Hosts, &out.Hosts
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ParentRefs != nil {
in, out := &in.ParentRefs, &out.ParentRefs
*out = make([]apisv1.ParentReference, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayApiSpec.
func (in *GatewayApiSpec) DeepCopy() *GatewayApiSpec {
if in == nil {
return nil
}
out := new(GatewayApiSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InProcessConfiguration) DeepCopyInto(out *InProcessConfiguration) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InProcessConfiguration.
func (in *InProcessConfiguration) DeepCopy() *InProcessConfiguration {
if in == nil {
return nil
}
out := new(InProcessConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InProcessConfiguration) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InProcessConfigurationList) DeepCopyInto(out *InProcessConfigurationList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]InProcessConfiguration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InProcessConfigurationList.
func (in *InProcessConfigurationList) DeepCopy() *InProcessConfigurationList {
if in == nil {
return nil
}
out := new(InProcessConfigurationList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *InProcessConfigurationList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InProcessConfigurationSpec) DeepCopyInto(out *InProcessConfigurationSpec) {
*out = *in
if in.EnvVars != nil {
in, out := &in.EnvVars, &out.EnvVars
*out = make([]v1.EnvVar, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InProcessConfigurationSpec.
func (in *InProcessConfigurationSpec) DeepCopy() *InProcessConfigurationSpec {
if in == nil {
return nil
}
out := new(InProcessConfigurationSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InProcessConfigurationStatus) DeepCopyInto(out *InProcessConfigurationStatus) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InProcessConfigurationStatus.
func (in *InProcessConfigurationStatus) DeepCopy() *InProcessConfigurationStatus {
if in == nil {
return nil
}
out := new(InProcessConfigurationStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *IngressSpec) DeepCopyInto(out *IngressSpec) {
*out = *in
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Hosts != nil {
in, out := &in.Hosts, &out.Hosts
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = make([]networkingv1.IngressTLS, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.IngressClassName != nil {
in, out := &in.IngressClassName, &out.IngressClassName
*out = new(string)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressSpec.
func (in *IngressSpec) DeepCopy() *IngressSpec {
if in == nil {
return nil
}
out := new(IngressSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Source) DeepCopyInto(out *Source) {
*out = *in

75
api/go.mod Normal file
View File

@ -0,0 +1,75 @@
module github.com/open-feature/open-feature-operator/apis
go 1.23.0
toolchain go1.23.3
require (
github.com/open-feature/flagd-schemas v0.2.9-0.20250529171004-2852d7772e6b
github.com/stretchr/testify v1.10.0
github.com/xeipuuv/gojsonschema v1.2.0
k8s.io/api v0.32.3
k8s.io/apimachinery v0.32.3
sigs.k8s.io/controller-runtime v0.20.1
sigs.k8s.io/gateway-api v1.2.1
)
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20250125003558-7fdb3d7e6fa0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/oauth2 v0.25.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.9.0 // indirect
golang.org/x/tools v0.29.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/protobuf v1.36.4 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.32.1 // indirect
k8s.io/client-go v0.32.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

198
api/go.sum Normal file
View File

@ -0,0 +1,198 @@
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20250125003558-7fdb3d7e6fa0 h1:my2ucqBZmv+cWHIhZNSIYKzgN8EBGyHdC7zD5sASRAg=
github.com/google/pprof v0.0.0-20250125003558-7fdb3d7e6fa0/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/open-feature/flagd-schemas v0.2.9-0.20240708163558-2aa89b314322 h1:5zbNHqcZAc9jlhSrC0onuVL2RPpvYcDaNvW2wOZBfUY=
github.com/open-feature/flagd-schemas v0.2.9-0.20240708163558-2aa89b314322/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
github.com/open-feature/flagd-schemas v0.2.9-0.20250127221449-bb763438abc5/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
github.com/open-feature/flagd-schemas v0.2.9-0.20250529171004-2852d7772e6b/go.mod h1:WKtwo1eW9/K6D+4HfgTXWBqCDzpvMhDa5eRxW7R5B2U=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw=
k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.20.1 h1:JbGMAG/X94NeM3xvjenVUaBjy6Ui4Ogd/J5ZtjZnHaE=
sigs.k8s.io/controller-runtime v0.20.1/go.mod h1:BrP3w158MwvB3ZbNpaAcIKkHQ7YGpYnzpoSTZ8E14WU=
sigs.k8s.io/gateway-api v1.2.1 h1:fZZ/+RyRb+Y5tGkwxFKuYuSRQHu9dZtbjenblleOLHM=
sigs.k8s.io/gateway-api v1.2.1/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -1,57 +0,0 @@
package common
import "fmt"
type SyncProviderType string
const (
SyncProviderKubernetes SyncProviderType = "kubernetes"
SyncProviderFilepath SyncProviderType = "file"
SyncProviderHttp SyncProviderType = "http"
SyncProviderGrpc SyncProviderType = "grpc"
SyncProviderFlagdProxy SyncProviderType = "flagd-proxy"
)
func (s SyncProviderType) IsKubernetes() bool {
return s == SyncProviderKubernetes
}
func (s SyncProviderType) IsHttp() bool {
return s == SyncProviderHttp
}
func (s SyncProviderType) IsFilepath() bool {
return s == SyncProviderFilepath
}
func (s SyncProviderType) IsGrpc() bool {
return s == SyncProviderGrpc
}
func (s SyncProviderType) IsFlagdProxy() bool {
return s == SyncProviderFlagdProxy
}
func TrueVal() *bool {
b := true
return &b
}
func FalseVal() *bool {
b := false
return &b
}
func EnvVarKey(prefix string, suffix string) string {
return fmt.Sprintf("%s_%s", prefix, suffix)
}
// unique string used to create unique volume mount and file name
func FeatureFlagConfigurationId(namespace, name string) string {
return EnvVarKey(namespace, name)
}
// unique key (and filename) for configMap data
func FeatureFlagConfigMapKey(namespace, name string) string {
return fmt.Sprintf("%s.flagd.json", FeatureFlagConfigurationId(namespace, name))
}

View File

@ -1,36 +0,0 @@
package common
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_FeatureFlagSource_SyncProvider(t *testing.T) {
k := SyncProviderKubernetes
f := SyncProviderFilepath
h := SyncProviderHttp
g := SyncProviderGrpc
require.True(t, k.IsKubernetes())
require.True(t, f.IsFilepath())
require.True(t, h.IsHttp())
require.True(t, g.IsGrpc())
require.False(t, f.IsKubernetes())
require.False(t, h.IsFilepath())
require.False(t, k.IsGrpc())
require.False(t, g.IsHttp())
}
func Test_FLagSourceConfiguration_EnvVarKey(t *testing.T) {
require.Equal(t, "pre_suf", EnvVarKey("pre", "suf"))
}
func Test_FLagSourceConfiguration_FeatureFlagConfigurationId(t *testing.T) {
require.Equal(t, "pre_suf", FeatureFlagConfigurationId("pre", "suf"))
}
func Test_FLagSourceConfiguration_FeatureFlagConfigMapKey(t *testing.T) {
require.Equal(t, "pre_suf.flagd.json", FeatureFlagConfigMapKey("pre", "suf"))
}

View File

@ -1,30 +0,0 @@
module github.com/open-feature/open-feature-operator/apis
go 1.21
require (
github.com/stretchr/testify v1.8.4
k8s.io/api v0.26.4
k8s.io/apimachinery v0.26.4
sigs.k8s.io/controller-runtime v0.14.6
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/text v0.7.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)

View File

@ -1,97 +0,0 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc=
github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94=
k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk=
k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs=
k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.14.6 h1:oxstGVvXGNnMvY7TAESYk+lzr6S3V5VFxQ6d92KcwQA=
sigs.k8s.io/controller-runtime v0.14.6/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@ -1,4 +1,6 @@
# ignore generated templates
templates/*.yaml
# templates/namespace.yaml is not generated, it's a special case
!templates/namespace.yaml
templates/crds/*.yaml
# the following files are not generated, they are special cases
!templates/namespace.yaml
!templates/admissionregistration.k8s.io_v1_validatingwebhookconfiguration_open-feature-operator-validating-webhook-configuration.yaml

View File

@ -13,12 +13,12 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: "v0.5.4" # x-release-please-version
version: "v0.8.7" # x-release-please-version
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "v0.5.4" # x-release-please-version
appVersion: "v0.8.7" # x-release-please-version
home: https://openfeature.dev
icon: https://open-feature.github.io/open-feature-operator/chart/open-feature-operator/openfeature-logo.png

View File

@ -97,52 +97,99 @@ The command removes all the Kubernetes components associated with the chart and
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------ |
| `defaultNamespace` | To override the namespace use the `--namespace` flag. This default is provided to ensure that the kustomize build charts in `/templates` deploy correctly when no `namespace` is provided via the `-n` flag. | `open-feature-operator-system` |
### namespace
| Name | Description | Value |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| `namespace.create` | Whether to create the namespace as part of this chart. | `true` |
| `namespace.labels` | Labels for the namespace if created as part of the chart. | `{}` |
| `namespace.annotations` | Annotations for the namespace if created as part of the chart. | `{}` |
| `imagePullSecrets` | Array of ImagePullSecret objects containing credentials for images pulled by the operator (flagdProxyConfiguration.image, flagdConfiguration.image, controllerManager.manager.image). Example: imagePullSecrets: [{"name": "my-secret"}] | `[]` |
| `labels` | Labels to apply to all of the pods in the operator. | `{}` |
| `annotations` | Annotations to apply to all of the pods in the operator. | `{}` |
### Mutating Webhook configuration
| Name | Description | Value |
| -------------------------------- | --------------------------------------------------------- | -------- |
| `mutatingWebhook.failurePolicy` | FailurePolicy when the webhook does not respond | `Ignore` |
| `mutatingWebhook.objectSelector` | ObjectSelector on which pods the mutatingWebhook will run | `{}` |
### Sidecar configuration
| Name | Description | Value |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| `sidecarConfiguration.port` | Sets the value of the `XXX_PORT` environment variable for the injected sidecar. | `8013` |
| `sidecarConfiguration.managementPort` | Sets the value of the `XXX_MANAGEMENT_PORT` environment variable for the injected sidecar. | `8014` |
| `sidecarConfiguration.socketPath` | Sets the value of the `XXX_SOCKET_PATH` environment variable for the injected sidecar. | `""` |
| `sidecarConfiguration.image.repository` | Sets the image for the injected sidecar. | `ghcr.io/open-feature/flagd` |
| `sidecarConfiguration.image.tag` | Sets the version tag for the injected sidecar. | `v0.9.0` |
| `sidecarConfiguration.providerArgs` | Used to append arguments to the sidecar startup command. This value is a comma separated string of key values separated by '=', e.g. `key=value,key2=value2` results in the appending of `--sync-provider-args key=value --sync-provider-args key2=value2`. | `""` |
| `sidecarConfiguration.envVarPrefix` | Sets the prefix for all environment variables set in the injected sidecar. | `FLAGD` |
| `sidecarConfiguration.defaultSyncProvider` | Sets the value of the `XXX_SYNC_PROVIDER` environment variable for the injected sidecar container. There are 4 valid sync providers: `kubernetes`, `grpc`, `file` and `http`. | `kubernetes` |
| `sidecarConfiguration.evaluator` | Sets the value of the `XXX_EVALUATOR` environment variable for the injected sidecar container. | `json` |
| `sidecarConfiguration.logFormat` | Sets the value of the `XXX_LOG_FORMAT` environment variable for the injected sidecar container. There are 2 valid log formats: `json` and `console`. | `json` |
| `sidecarConfiguration.probesEnabled` | Enable or Disable Liveness and Readiness probes of the flagd sidecar. When enabled, HTTP probes( paths - `/readyz`, `/healthz`) are set with an initial delay of 5 seconds. | `true` |
| `sidecarConfiguration.debugLogging` | Controls the addition of the `--debug` flag to the container startup arguments. | `false` |
| `sidecarConfiguration.otelCollectorUri` | Otel exporter uri. | `""` |
| `sidecarConfiguration.resources` | Override resources of the flagd sidecar. | `{}` |
| Name | Description | Value |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| `sidecarConfiguration.port` | Sets the value of the `XXX_PORT` environment variable for the injected sidecar. | `8013` |
| `sidecarConfiguration.managementPort` | Sets the value of the `XXX_MANAGEMENT_PORT` environment variable for the injected sidecar. | `8014` |
| `sidecarConfiguration.socketPath` | Sets the value of the `XXX_SOCKET_PATH` environment variable for the injected sidecar. | `""` |
| `sidecarConfiguration.image.repository` | Sets the image for the injected sidecar. | `ghcr.io/open-feature/flagd` |
| `sidecarConfiguration.image.tag` | Sets the version tag for the injected sidecar. | `v0.12.4` |
| `sidecarConfiguration.providerArgs` | Used to append arguments to the sidecar startup command. This value is a comma separated string of key values separated by '=', e.g. `key=value,key2=value2` results in the appending of `--sync-provider-args key=value --sync-provider-args key2=value2`. | `""` |
| `sidecarConfiguration.envVarPrefix` | Sets the prefix for all environment variables set in the injected sidecar. | `FLAGD` |
| `sidecarConfiguration.defaultSyncProvider` | Sets the value of the `XXX_SYNC_PROVIDER` environment variable for the injected sidecar container. There are 4 valid sync providers: `kubernetes`, `grpc`, `file` and `http`. | `kubernetes` |
| `sidecarConfiguration.evaluator` | Sets the value of the `XXX_EVALUATOR` environment variable for the injected sidecar container. | `json` |
| `sidecarConfiguration.logFormat` | Sets the value of the `XXX_LOG_FORMAT` environment variable for the injected sidecar container. There are 2 valid log formats: `json` and `console`. | `json` |
| `sidecarConfiguration.probesEnabled` | Enable or Disable Liveness and Readiness probes of the flagd sidecar. When enabled, HTTP probes( paths - `/readyz`, `/healthz`) are set with an initial delay of 5 seconds. | `true` |
| `sidecarConfiguration.debugLogging` | Controls the addition of the `--debug` flag to the container startup arguments. | `false` |
| `sidecarConfiguration.otelCollectorUri` | Otel exporter uri. | `""` |
| `sidecarConfiguration.resources.limits.cpu` | Sets cpu resource limits for kube-rbac-proxy. | `500m` |
| `sidecarConfiguration.resources.limits.memory` | Sets memory resource limits for kube-rbac-proxy. | `64Mi` |
| `sidecarConfiguration.resources.requests.cpu` | Sets cpu resource requests for kube-rbac-proxy. | `200m` |
| `sidecarConfiguration.resources.requests.memory` | Sets memory resource requests for kube-rbac-proxy. | `32Mi` |
### In-process configuration
| Name | Description | Value |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------- |
| `inProcessConfiguration.port` | Sets the value of the `XXX_PORT` environment variable for the pod containers. | `8015` |
| `inProcessConfiguration.host` | Sets the value of the `XXX_HOST` environment variable for the pod containers. | `localhost` |
| `inProcessConfiguration.socketPath` | Sets the value of the `XXX_SOCKET_PATH` environment variable for the pod containers. | `""` |
| `inProcessConfiguration.tls` | Sets the value of the `XXX_TLS` environment variable for the pod containers. | `false` |
| `inProcessConfiguration.offlineFlagSourcePath` | Sets the value of the `XXX_OFFLINE_FLAG_SOURCE_PATH` environment variable for the pod containers. | `""` |
| `inProcessConfiguration.selector` | Sets the value of the `XXX_SELECTOR` environment variable for the pod containers. | `""` |
| `inProcessConfiguration.envVarPrefix` | Sets the value of the `XXX_ENV_VAR_PREFIX` environment variable for the pod containers. | `FLAGD` |
| `inProcessConfiguration.cache.type` | Sets the value of the `XXX_CACHE` environment variable for the pod containers. | `lru` |
| `inProcessConfiguration.cache.size` | Sets the value of the `XXX_CACHE_MAX_SIZE` environment variable for the pod containers. | `1000` |
### Flagd-proxy configuration
| Name | Description | Value |
| ------------------------------------------ | ------------------------------------------------------------------------------- | ---------------------------------- |
| `flagdProxyConfiguration.replicaCount` | sets the number of replicas for the flagd-proxy deployment. | `1` |
| `flagdProxyConfiguration.port` | Sets the port to expose the sync API on. | `8015` |
| `flagdProxyConfiguration.managementPort` | Sets the port to expose the management API on. | `8016` |
| `flagdProxyConfiguration.image.repository` | Sets the image for the flagd-proxy deployment. | `ghcr.io/open-feature/flagd-proxy` |
| `flagdProxyConfiguration.image.tag` | Sets the tag for the flagd-proxy deployment. | `v0.5.0` |
| `flagdProxyConfiguration.image.tag` | Sets the tag for the flagd-proxy deployment. | `v0.7.4` |
| `flagdProxyConfiguration.debugLogging` | Controls the addition of the `--debug` flag to the container startup arguments. | `false` |
### Flagd configuration
| Name | Description | Value |
| ------------------------------------- | ------------------------------------------------------------------------------- | ---------------------------- |
| `flagdConfiguration.port` | Sets the port to expose the flagd API on. | `8013` |
| `flagdConfiguration.ofrepPort` | Sets the port to expose the ofrep API on. | `8016` |
| `flagdConfiguration.syncPort` | Sets the port to expose the sync API on. | `8015` |
| `flagdConfiguration.managementPort` | Sets the port to expose the management API on. | `8014` |
| `flagdConfiguration.image.repository` | Sets the image for the flagd deployment. | `ghcr.io/open-feature/flagd` |
| `flagdConfiguration.image.tag` | Sets the tag for the flagd deployment. | `v0.12.4` |
| `flagdConfiguration.debugLogging` | Controls the addition of the `--debug` flag to the container startup arguments. | `false` |
### Operator resource configuration
| Name | Description | Value |
| ------------------------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------- |
| `controllerManager.kubeRbacProxy.image.repository` | Sets the image for the kube-rbac-proxy. | `gcr.io/kubebuilder/kube-rbac-proxy` |
| `controllerManager.kubeRbacProxy.image.tag` | Sets the version tag for the kube-rbac-proxy. | `v0.14.1` |
| `controllerManager.kubeRbacProxy.resources.limits.cpu` | Sets cpu resource limits for kube-rbac-proxy. | `500m` |
| `controllerManager.kubeRbacProxy.resources.limits.memory` | Sets memory resource limits for kube-rbac-proxy. | `128Mi` |
| `controllerManager.kubeRbacProxy.resources.requests.cpu` | Sets cpu resource requests for kube-rbac-proxy. | `5m` |
| `controllerManager.kubeRbacProxy.resources.requests.memory` | Sets memory resource requests for kube-rbac-proxy. | `64Mi` |
| `controllerManager.manager.image.repository` | Sets the image for the operator. | `ghcr.io/open-feature/open-feature-operator` |
| `controllerManager.manager.image.tag` | Sets the version tag for the operator. | `v0.5.3` |
| `controllerManager.manager.resources.limits.cpu` | Sets cpu resource limits for operator. | `500m` |
| `controllerManager.manager.resources.limits.memory` | Sets memory resource limits for operator. | `128Mi` |
| `controllerManager.manager.resources.requests.cpu` | Sets cpu resource requests for operator. | `10m` |
| `controllerManager.manager.resources.requests.memory` | Sets memory resource requests for operator. | `64Mi` |
| `controllerManager.replicas` | Sets number of replicas of the OpenFeature operator pod. | `1` |
| `managerConfig.controllerManagerConfigYaml.health.healthProbeBindAddress` | Sets the bind address for health probes. | `:8081` |
| `managerConfig.controllerManagerConfigYaml.metrics.bindAddress` | Sets the bind address for metrics. | `127.0.0.1:8080` |
| `managerConfig.controllerManagerConfigYaml.webhook.port` | Sets the bind address for webhook. | `9443` |
| Name | Description | Value |
| ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| `controllerManager.manager.image.repository` | Sets the image for the operator. | `ghcr.io/open-feature/open-feature-operator` |
| `controllerManager.manager.image.tag` | Sets the version tag for the operator. | `v0.8.7` |
| `controllerManager.manager.resources.limits.cpu` | Sets cpu resource limits for operator. | `500m` |
| `controllerManager.manager.resources.limits.memory` | Sets memory resource limits for operator. | `128Mi` |
| `controllerManager.manager.resources.requests.cpu` | Sets cpu resource requests for operator. | `10m` |
| `controllerManager.manager.resources.requests.memory` | Sets memory resource requests for operator. | `64Mi` |
| `controllerManager.manager.hostNetwork` | Should the injector pods run on the host network (useful when using an alternate CNI in EKS) | `false` |
| `controllerManager.manager.dnsPolicy` | Pod DNS resolution scheme. Should be `ClusterFirstWithHostNet` if hostNetwork is true, `ClusterFirst` otherwise. | `ClusterFirst` |
| `controllerManager.replicas` | Sets number of replicas of the OpenFeature operator pod. | `1` |
| `managerConfig.flagsValidationEnabled` | Enables the validating webhook for FeatureFlag CR. | `true` |
| `managerConfig.controllerManagerConfigYaml.health.healthProbeBindAddress` | Sets the bind address for health probes. | `:8081` |
| `managerConfig.controllerManagerConfigYaml.metrics.bindAddress` | Sets the bind address for metrics (combined with bindPort). | `127.0.0.1` |
| `managerConfig.controllerManagerConfigYaml.metrics.bindPort` | Sets the bind port for metrics. | `8080` |
| `managerConfig.controllerManagerConfigYaml.webhook.port` | Sets the bind address for webhook. | `9443` |

View File

@ -0,0 +1,29 @@
{{ if eq .Values.managerConfig.flagsValidationEnabled "true" }}
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
annotations:
cert-manager.io/inject-ca-from: '{{ include "chart.namespace" . }}/open-feature-operator-serving-cert'
name: open-feature-operator-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: open-feature-operator-webhook-service
namespace: '{{ include "chart.namespace" . }}'
path: /validate-core-openfeature-dev-v1beta1-featureflag
failurePolicy: Fail
name: vfeatureflag.kb.io
rules:
- apiGroups:
- core.openfeature.dev
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- featureflags
sideEffects: None
{{ end }}

View File

@ -1,10 +1,17 @@
# Only deploy the namespace if the default is being used (helm install should fail if the namespace isnt present)
# when one is defined with -n
{{ if eq ( include "chart.namespace" . ) .Values.defaultNamespace }}
{{- if and (eq (include "chart.namespace" .) .Values.defaultNamespace) .Values.namespace.create }}
apiVersion: v1
kind: Namespace
metadata:
name: '{{ include "chart.namespace" . }}'
labels:
control-plane: controller-manager
name: '{{ include "chart.namespace" . }}'
{{ end }}
{{- range $key, $value := $.Values.namespace.labels }}
{{ $key }}: {{ $value | quote }}
{{- end }}
annotations:
{{- range $key, $value := $.Values.namespace.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
{{ end }}

View File

@ -2,7 +2,28 @@
## @section Global
## @param defaultNamespace To override the namespace use the `--namespace` flag. This default is provided to ensure that the kustomize build charts in `/templates` deploy correctly when no `namespace` is provided via the `-n` flag.
defaultNamespace: open-feature-operator-system
## @section namespace
namespace:
## @param namespace.create Whether to create the namespace as part of this chart.
create: true
## @param namespace.labels Labels for the namespace if created as part of the chart.
labels: {}
## @param namespace.annotations Annotations for the namespace if created as part of the chart.
annotations: {}
## @param imagePullSecrets Array of ImagePullSecret objects containing credentials for images pulled by the operator (flagdProxyConfiguration.image, flagdConfiguration.image, controllerManager.manager.image). Example: imagePullSecrets: [{"name": "my-secret"}]
imagePullSecrets: []
## @param labels Labels to apply to all of the pods in the operator.
labels: {}
## @param annotations Annotations to apply to all of the pods in the operator.
annotations: {}
## @section Mutating Webhook configuration
mutatingWebhook:
## @param mutatingWebhook.failurePolicy FailurePolicy when the webhook does not respond
failurePolicy: Ignore
## @param mutatingWebhook.objectSelector ObjectSelector on which pods the mutatingWebhook will run
objectSelector: {}
## @section Sidecar configuration
sidecarConfiguration:
## @param sidecarConfiguration.port Sets the value of the `XXX_PORT` environment variable for the injected sidecar.
@ -16,7 +37,7 @@ sidecarConfiguration:
## @param sidecarConfiguration.image.repository Sets the image for the injected sidecar.
repository: "ghcr.io/open-feature/flagd"
## @param sidecarConfiguration.image.tag Sets the version tag for the injected sidecar.
tag: v0.9.0
tag: v0.12.4
## @param sidecarConfiguration.providerArgs Used to append arguments to the sidecar startup command. This value is a comma separated string of key values separated by '=', e.g. `key=value,key2=value2` results in the appending of `--sync-provider-args key=value --sync-provider-args key2=value2`.
providerArgs: ""
## @param sidecarConfiguration.envVarPrefix Sets the prefix for all environment variables set in the injected sidecar.
@ -33,11 +54,44 @@ sidecarConfiguration:
debugLogging: false
## @param sidecarConfiguration.otelCollectorUri Otel exporter uri.
otelCollectorUri: ""
## @param sidecarConfiguration.resources Override resources of the flagd sidecar.
resources: { }
resources:
limits:
## @param sidecarConfiguration.resources.limits.cpu Sets cpu resource limits for kube-rbac-proxy.
cpu: 500m
## @param sidecarConfiguration.resources.limits.memory Sets memory resource limits for kube-rbac-proxy.
memory: 64Mi
requests:
## @param sidecarConfiguration.resources.requests.cpu Sets cpu resource requests for kube-rbac-proxy.
cpu: 200m
## @param sidecarConfiguration.resources.requests.memory Sets memory resource requests for kube-rbac-proxy.
memory: 32Mi
## @section In-process configuration
inProcessConfiguration:
## @param inProcessConfiguration.port Sets the value of the `XXX_PORT` environment variable for the pod containers.
port: 8015
## @param inProcessConfiguration.host Sets the value of the `XXX_HOST` environment variable for the pod containers.
host: "localhost"
## @param inProcessConfiguration.socketPath Sets the value of the `XXX_SOCKET_PATH` environment variable for the pod containers.
socketPath: ""
## @param inProcessConfiguration.tls Sets the value of the `XXX_TLS` environment variable for the pod containers.
tls: "false"
## @param inProcessConfiguration.offlineFlagSourcePath Sets the value of the `XXX_OFFLINE_FLAG_SOURCE_PATH` environment variable for the pod containers.
offlineFlagSourcePath: ""
## @param inProcessConfiguration.selector Sets the value of the `XXX_SELECTOR` environment variable for the pod containers.
selector: ""
## @param inProcessConfiguration.envVarPrefix Sets the value of the `XXX_ENV_VAR_PREFIX` environment variable for the pod containers.
envVarPrefix: "FLAGD"
cache:
## @param inProcessConfiguration.cache.type Sets the value of the `XXX_CACHE` environment variable for the pod containers.
type: "lru"
## @param inProcessConfiguration.cache.size Sets the value of the `XXX_CACHE_MAX_SIZE` environment variable for the pod containers.
size: 1000
## @section Flagd-proxy configuration
flagdProxyConfiguration:
## @param flagdProxyConfiguration.replicaCount sets the number of replicas for the flagd-proxy deployment.
replicaCount: 1
## @param flagdProxyConfiguration.port Sets the port to expose the sync API on.
port: 8015
## @param flagdProxyConfiguration.managementPort Sets the port to expose the management API on.
@ -46,35 +100,36 @@ flagdProxyConfiguration:
## @param flagdProxyConfiguration.image.repository Sets the image for the flagd-proxy deployment.
repository: "ghcr.io/open-feature/flagd-proxy"
## @param flagdProxyConfiguration.image.tag Sets the tag for the flagd-proxy deployment.
tag: v0.5.0
tag: v0.7.4
## @param flagdProxyConfiguration.debugLogging Controls the addition of the `--debug` flag to the container startup arguments.
debugLogging: false
## @section Flagd configuration
flagdConfiguration:
## @param flagdConfiguration.port Sets the port to expose the flagd API on.
port: 8013
## @param flagdConfiguration.ofrepPort Sets the port to expose the ofrep API on.
ofrepPort: 8016
## @param flagdConfiguration.syncPort Sets the port to expose the sync API on.
syncPort: 8015
## @param flagdConfiguration.managementPort Sets the port to expose the management API on.
managementPort: 8014
image:
## @param flagdConfiguration.image.repository Sets the image for the flagd deployment.
repository: "ghcr.io/open-feature/flagd"
## @param flagdConfiguration.image.tag Sets the tag for the flagd deployment.
tag: v0.12.4
## @param flagdConfiguration.debugLogging Controls the addition of the `--debug` flag to the container startup arguments.
debugLogging: false
## @section Operator resource configuration
controllerManager:
kubeRbacProxy:
image:
## @param controllerManager.kubeRbacProxy.image.repository Sets the image for the kube-rbac-proxy.
repository: gcr.io/kubebuilder/kube-rbac-proxy
## @param controllerManager.kubeRbacProxy.image.tag Sets the version tag for the kube-rbac-proxy.
tag: "v0.14.1"
resources:
limits:
## @param controllerManager.kubeRbacProxy.resources.limits.cpu Sets cpu resource limits for kube-rbac-proxy.
cpu: 500m
## @param controllerManager.kubeRbacProxy.resources.limits.memory Sets memory resource limits for kube-rbac-proxy.
memory: 128Mi
requests:
## @param controllerManager.kubeRbacProxy.resources.requests.cpu Sets cpu resource requests for kube-rbac-proxy.
cpu: 5m
## @param controllerManager.kubeRbacProxy.resources.requests.memory Sets memory resource requests for kube-rbac-proxy.
memory: 64Mi
manager:
image:
## @param controllerManager.manager.image.repository Sets the image for the operator.
repository: ghcr.io/open-feature/open-feature-operator
## @param controllerManager.manager.image.tag Sets the version tag for the operator.
tag: v0.5.4 # x-release-please-version
tag: v0.8.7 # x-release-please-version
resources:
limits:
## @param controllerManager.manager.resources.limits.cpu Sets cpu resource limits for operator.
@ -86,17 +141,25 @@ controllerManager:
cpu: 10m
## @param controllerManager.manager.resources.requests.memory Sets memory resource requests for operator.
memory: 64Mi
## @param controllerManager.manager.hostNetwork Should the injector pods run on the host network (useful when using an alternate CNI in EKS)
hostNetwork: false
## @param controllerManager.manager.dnsPolicy Pod DNS resolution scheme. Should be `ClusterFirstWithHostNet` if hostNetwork is true, `ClusterFirst` otherwise.
dnsPolicy: ClusterFirst
## @param controllerManager.replicas Sets number of replicas of the OpenFeature operator pod.
replicas: 1
managerConfig:
## @param managerConfig.flagsValidationEnabled Enables the validating webhook for FeatureFlag CR.
flagsValidationEnabled: "true"
controllerManagerConfigYaml:
health:
## @param managerConfig.controllerManagerConfigYaml.health.healthProbeBindAddress Sets the bind address for health probes.
healthProbeBindAddress: :8081
metrics:
## @param managerConfig.controllerManagerConfigYaml.metrics.bindAddress Sets the bind address for metrics.
bindAddress: 127.0.0.1:8080
metrics:
## @param managerConfig.controllerManagerConfigYaml.metrics.bindAddress Sets the bind address for metrics (combined with bindPort).
bindAddress: 127.0.0.1
## @param managerConfig.controllerManagerConfigYaml.metrics.bindPort Sets the bind port for metrics.
bindPort: 8080
webhook:
## @param managerConfig.controllerManagerConfigYaml.webhook.port Sets the bind address for webhook.
port: 9443

522
cmd/main.go Normal file
View File

@ -0,0 +1,522 @@
/*
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"context"
"crypto/tls"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/kelseyhightower/envconfig"
corev1beta1 "github.com/open-feature/open-feature-operator/apis/core/v1beta1"
"github.com/open-feature/open-feature-operator/internal/common"
"github.com/open-feature/open-feature-operator/internal/common/flagdinjector"
"github.com/open-feature/open-feature-operator/internal/common/flagdproxy"
"github.com/open-feature/open-feature-operator/internal/common/types"
"github.com/open-feature/open-feature-operator/internal/common/utils"
"github.com/open-feature/open-feature-operator/internal/controller/core/featureflagsource"
"github.com/open-feature/open-feature-operator/internal/controller/core/flagd"
flagdResources "github.com/open-feature/open-feature-operator/internal/controller/core/flagd/resources"
webhooks "github.com/open-feature/open-feature-operator/internal/webhook"
"go.uber.org/zap/zapcore"
appsV1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
"sigs.k8s.io/controller-runtime/pkg/client"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
gatewayApiv1 "sigs.k8s.io/gateway-api/apis/v1"
)
const (
healthProbeBindAddressFlagName = "health-probe-bind-address"
metricsBindAddressFlagName = "metrics-bind-address"
verboseFlagName = "verbose"
leaderElectFlagName = "leader-elect"
sidecarCpuLimitFlagName = "sidecar-cpu-limit"
sidecarCpuLimitDefault = "0.5"
sidecarRamLimitFlagName = "sidecar-ram-limit"
sidecarRamLimitDefault = "64M"
sidecarCpuRequestFlagName = "sidecar-cpu-request"
sidecarCpuRequestDefault = "0.2"
sidecarRamRequestFlagName = "sidecar-ram-request"
sidecarRamRequestDefault = "32M"
imagePullSecretFlagName = "image-pull-secrets"
imagePullSecretFlagDefault = ""
labelsFlagName = "labels"
labelsFlagDefault = ""
annotationsFlagName = "annotations"
annotationsFlagDefault = ""
)
var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
metricsAddr string
metricsCertPath, metricsCertName, metricsCertKey string
webhookCertPath, webhookCertName, webhookCertKey string
secureMetrics bool
enableHTTP2 bool
tlsOpts []func(*tls.Config)
enableLeaderElection bool
probeAddr string
verbose bool
sidecarCpuLimit, sidecarRamLimit, sidecarCpuRequest, sidecarRamRequest string
imagePullSecrets string
labels string
annotations string
)
// StringToMap transforms a string into a map[string]string
func StringToMap(s string) map[string]string {
m := map[string]string{}
for _, pair := range strings.Split(s, ",") {
kv := strings.SplitN(pair, ":", 2)
if len(kv) == 2 {
m[kv[0]] = kv[1]
}
}
return m
}
// CommaSeparatedStringToSlice transforms a comma-separated string into a slice of strings
func CommaSeparatedStringToSlice(s string) []string {
if s == "" {
return []string{}
}
return strings.Split(s, ",")
}
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(corev1beta1.AddToScheme(scheme))
utilruntime.Must(gatewayApiv1.Install(scheme))
//+kubebuilder:scaffold:scheme
}
//nolint:funlen,gocyclo,gocognit
func main() {
var env types.EnvConfig
if err := envconfig.Process("", &env); err != nil {
log.Fatalf("Failed to process env var: %s", err)
}
flag.StringVar(&metricsAddr, metricsBindAddressFlagName, ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, healthProbeBindAddressFlagName, ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&verbose, verboseFlagName, true, "Disable verbose logging")
flag.BoolVar(&enableLeaderElection, leaderElectFlagName, false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
flag.BoolVar(&secureMetrics, "metrics-secure", true,
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
flag.StringVar(&webhookCertPath, "webhook-cert-path", "", "The directory that contains the webhook certificate.")
flag.StringVar(&webhookCertName, "webhook-cert-name", "tls.crt", "The name of the webhook certificate file.")
flag.StringVar(&webhookCertKey, "webhook-cert-key", "tls.key", "The name of the webhook key file.")
flag.StringVar(&metricsCertPath, "metrics-cert-path", "",
"The directory that contains the metrics server certificate.")
flag.StringVar(&metricsCertName, "metrics-cert-name", "tls.crt", "The name of the metrics server certificate file.")
flag.StringVar(&metricsCertKey, "metrics-cert-key", "tls.key", "The name of the metrics server key file.")
flag.BoolVar(&enableHTTP2, "enable-http2", false,
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
// the following default values are chosen as a result of load testing: https://github.com/open-feature/flagd/blob/main/tests/loadtest/README.MD#performance-observations
flag.StringVar(&sidecarCpuLimit, sidecarCpuLimitFlagName, sidecarCpuLimitDefault, "sidecar CPU limit, in cores. (500m = .5 cores)")
flag.StringVar(&sidecarRamLimit, sidecarRamLimitFlagName, sidecarRamLimitDefault, "sidecar memory limit, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)")
flag.StringVar(&sidecarCpuRequest, sidecarCpuRequestFlagName, sidecarCpuRequestDefault, "sidecar CPU minimum, in cores. (500m = .5 cores)")
flag.StringVar(&sidecarRamRequest, sidecarRamRequestFlagName, sidecarRamRequestDefault, "sidecar memory minimum, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)")
flag.StringVar(&imagePullSecrets, imagePullSecretFlagName, imagePullSecretFlagDefault, "Comma-delimited list of secrets containing credentials to pull images.")
flag.StringVar(&labels, labelsFlagName, labelsFlagDefault, "Map of labels to add to the deployed pods. Formatted like key1:value1,key2:value2,key3:value3")
flag.StringVar(&annotations, annotationsFlagName, annotationsFlagDefault, "Map of annotations to add to the deployed pods. Formatted like key1:value1,key2:value2,key3:value3")
flag.Parse()
level := zapcore.InfoLevel
if verbose {
level = zapcore.DebugLevel
}
opts := zap.Options{
Development: verbose,
Level: level,
}
opts.BindFlags(flag.CommandLine)
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
// if the enable-http2 flag is false (the default), http/2 should be disabled
// due to its vulnerabilities. More specifically, disabling http/2 will
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
// Rapid Reset CVEs. For more information see:
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
// - https://github.com/advisories/GHSA-4374-p667-p6c8
disableHTTP2 := func(c *tls.Config) {
setupLog.Info("disabling http/2")
c.NextProtos = []string{"http/1.1"}
}
if !enableHTTP2 {
tlsOpts = append(tlsOpts, disableHTTP2)
}
// Create watchers for metrics and webhooks certificates
var metricsCertWatcher, webhookCertWatcher *certwatcher.CertWatcher
// Initial webhook TLS options
webhookTLSOpts := tlsOpts
if len(webhookCertPath) > 0 {
setupLog.Info("Initializing webhook certificate watcher using provided certificates",
"webhook-cert-path", webhookCertPath, "webhook-cert-name", webhookCertName, "webhook-cert-key", webhookCertKey)
var err error
webhookCertWatcher, err = certwatcher.New(
filepath.Join(webhookCertPath, webhookCertName),
filepath.Join(webhookCertPath, webhookCertKey),
)
if err != nil {
setupLog.Error(err, "Failed to initialize webhook certificate watcher")
os.Exit(1)
}
webhookTLSOpts = append(webhookTLSOpts, func(config *tls.Config) {
config.GetCertificate = webhookCertWatcher.GetCertificate
})
}
webhookServer := webhook.NewServer(webhook.Options{
TLSOpts: webhookTLSOpts,
Port: 9443,
})
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
// More info:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.20.0/pkg/metrics/server
// - https://book.kubebuilder.io/reference/metrics.html
metricsServerOptions := metricsserver.Options{
BindAddress: metricsAddr,
SecureServing: secureMetrics,
TLSOpts: tlsOpts,
}
if secureMetrics {
// FilterProvider is used to protect the metrics endpoint with authn/authz.
// These configurations ensure that only authorized users and service accounts
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.20.0/pkg/metrics/filters#WithAuthenticationAndAuthorization
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
}
// If the certificate is not specified, controller-runtime will automatically
// generate self-signed certificates for the metrics server. While convenient for development and testing,
// this setup is not recommended for production.
//
// - [METRICS-WITH-CERTS] at config/default/kustomization.yaml to generate and use certificates
// managed by cert-manager for the metrics server.
// - [PROMETHEUS-WITH-CERTS] at config/prometheus/kustomization.yaml for TLS certification.
if len(metricsCertPath) > 0 {
setupLog.Info("Initializing metrics certificate watcher using provided certificates",
"metrics-cert-path", metricsCertPath, "metrics-cert-name", metricsCertName, "metrics-cert-key", metricsCertKey)
var err error
metricsCertWatcher, err = certwatcher.New(
filepath.Join(metricsCertPath, metricsCertName),
filepath.Join(metricsCertPath, metricsCertKey),
)
if err != nil {
setupLog.Error(err, "to initialize metrics certificate watcher", "error", err)
os.Exit(1)
}
metricsServerOptions.TLSOpts = append(metricsServerOptions.TLSOpts, func(config *tls.Config) {
config.GetCertificate = metricsCertWatcher.GetCertificate
})
}
resources, err := processResources()
if err != nil {
os.Exit(1)
}
disableCacheFor := []client.Object{&v1.ClusterRoleBinding{}}
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: server.Options{
BindAddress: metricsAddr,
},
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "131bf64c.openfeature.dev",
Client: ctrlclient.Options{
Cache: &ctrlclient.CacheOptions{
DisableFor: disableCacheFor,
},
},
WebhookServer: webhookServer,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
if metricsCertWatcher != nil {
setupLog.Info("Adding metrics certificate watcher to manager")
if err := mgr.Add(metricsCertWatcher); err != nil {
setupLog.Error(err, "unable to add metrics certificate watcher to manager")
os.Exit(1)
}
}
if webhookCertWatcher != nil {
setupLog.Info("Adding webhook certificate watcher to manager")
if err := mgr.Add(webhookCertWatcher); err != nil {
setupLog.Error(err, "unable to add webhook certificate watcher to manager")
os.Exit(1)
}
}
// setup indexer for backfilling permissions on the flagd-kubernetes-sync role binding
if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&corev1.Pod{},
fmt.Sprintf("%s/%s", common.PodOpenFeatureAnnotationPath, common.AllowKubernetesSyncAnnotation),
webhooks.OpenFeatureEnabledAnnotationIndex,
); err != nil {
setupLog.Error(
err,
"unable to create indexer",
"webhook",
fmt.Sprintf("%s/%s", common.PodOpenFeatureAnnotationPath, common.AllowKubernetesSyncAnnotation),
)
os.Exit(1)
}
if err := mgr.GetFieldIndexer().IndexField(
context.Background(),
&appsV1.Deployment{},
fmt.Sprintf("%s/%s", common.OpenFeatureAnnotationPath, common.FeatureFlagSourceAnnotation),
common.FeatureFlagSourceIndex,
); err != nil {
setupLog.Error(
err,
"unable to create indexer",
"webhook",
fmt.Sprintf("%s/%s", common.OpenFeatureAnnotationPath, common.FeatureFlagSourceAnnotation),
)
os.Exit(1)
}
labelsMap := StringToMap(labels)
annotationsMap := StringToMap(annotations)
kph := flagdproxy.NewFlagdProxyHandler(
flagdproxy.NewFlagdProxyConfiguration(
env,
CommaSeparatedStringToSlice(imagePullSecrets),
labelsMap,
annotationsMap,
),
mgr.GetClient(),
ctrl.Log.WithName("FeatureFlagSource FlagdProxyHandler"),
)
flagSourceController := &featureflagsource.FeatureFlagSourceReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: ctrl.Log.WithName("FeatureFlagSource Controller"),
FlagdProxy: kph,
FlagdProxyBackoff: &utils.ExponentialBackoff{
StartDelay: time.Second,
MaxDelay: time.Minute,
},
}
if err = flagSourceController.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "FeatureFlagSource")
os.Exit(1)
}
flagdContainerInjector := &flagdinjector.FlagdContainerInjector{
Client: mgr.GetClient(),
Logger: ctrl.Log.WithName("flagd-container injector"),
FlagdProxyConfig: kph.Config(),
FlagdResourceRequirements: *resources,
Image: env.SidecarImage,
Tag: env.SidecarTag,
}
flagdControllerLogger := ctrl.Log.WithName("Flagd Controller")
flagdResourceReconciler := &flagd.ResourceReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Log: flagdControllerLogger,
}
flagdConfig := flagd.NewFlagdConfiguration(
env,
CommaSeparatedStringToSlice(imagePullSecrets),
labelsMap,
annotationsMap,
)
if err = (&flagd.FlagdReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
ResourceReconciler: flagdResourceReconciler,
FlagdDeployment: &flagdResources.FlagdDeployment{
Client: mgr.GetClient(),
Log: flagdControllerLogger,
FlagdInjector: flagdContainerInjector,
FlagdConfig: flagdConfig,
},
FlagdService: &flagdResources.FlagdService{
FlagdConfig: flagdConfig,
},
FlagdIngress: &flagdResources.FlagdIngress{
FlagdConfig: flagdConfig,
},
FlagdGatewayApiHttpRoute: &flagdResources.FlagdGatewayApiHttpRoute{
FlagdConfig: flagdConfig,
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Flagd")
os.Exit(1)
}
if env.FlagsValidationEnabled {
if err = (&webhooks.FeatureFlagCustomValidator{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create the validation webhook for FeatureFlag CRD", "webhook", "FeatureFlag")
os.Exit(1)
}
}
//+kubebuilder:scaffold:builder
hookServer := mgr.GetWebhookServer()
podMutator := &webhooks.PodMutator{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("mutating-pod-webhook"),
FlagdProxyConfig: kph.Config(),
Env: env,
FlagdInjector: flagdContainerInjector,
}
if err := podMutator.InjectDecoder(admission.NewDecoder(mgr.GetScheme())); err != nil {
setupLog.Error(err, "unable to inject decoder into mutating webhook")
os.Exit(1)
}
hookServer.Register("/mutate-v1-pod", &webhook.Admission{Handler: podMutator})
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
os.Exit(1)
}
if err := mgr.AddReadyzCheck("readyz", podMutator.IsReady); err != nil {
setupLog.Error(err, "unable to set up ready check")
os.Exit(1)
}
setupLog.Info("starting manager")
ctx := ctrl.SetupSignalHandler()
errChan := make(chan error, 1)
go func(chan error) {
if err := mgr.Start(ctx); err != nil {
errChan <- err
}
}(errChan)
setupLog.Info("restoring flagd-kubernetes-sync cluster role binding subjects from current cluster state")
// backfill can be handled asynchronously, so we do not need to block via the channel
go func() {
if err := podMutator.BackfillPermissions(ctx); err != nil {
setupLog.Error(err, "podMutator backfill permissions error")
}
}()
if err := <-errChan; err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
}
func processResources() (*corev1.ResourceRequirements, error) {
cpuLimitResource, err := resource.ParseQuantity(sidecarCpuLimit)
if err != nil {
setupLog.Error(err, "parse sidecar cpu limit", sidecarCpuLimitFlagName, sidecarCpuLimit)
return nil, err
}
ramLimitResource, err := resource.ParseQuantity(sidecarRamLimit)
if err != nil {
setupLog.Error(err, "parse sidecar ram limit", sidecarRamLimitFlagName, sidecarRamLimit)
return nil, err
}
cpuRequestResource, err := resource.ParseQuantity(sidecarCpuRequest)
if err != nil {
setupLog.Error(err, "parse sidecar cpu request", sidecarCpuRequestFlagName, sidecarCpuRequest)
return nil, err
}
ramRequestResource, err := resource.ParseQuantity(sidecarRamRequest)
if err != nil {
setupLog.Error(err, "parse sidecar ram request", sidecarRamRequestFlagName, sidecarRamRequest)
return nil, err
}
if cpuRequestResource.Value() > cpuLimitResource.Value() ||
ramRequestResource.Value() > ramLimitResource.Value() {
setupLog.Error(err, "sidecar resource request is higher than the resource maximum")
return nil, err
}
return &corev1.ResourceRequirements{
Limits: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: cpuLimitResource,
corev1.ResourceMemory: ramLimitResource,
},
Requests: map[corev1.ResourceName]resource.Quantity{
corev1.ResourceCPU: cpuRequestResource,
corev1.ResourceMemory: ramRequestResource,
},
}, nil
}

View File

@ -1,79 +0,0 @@
package common
import (
"context"
"errors"
"fmt"
"time"
api "github.com/open-feature/open-feature-operator/apis/core/v1beta1"
appsV1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
ReconcileErrorInterval = 10 * time.Second
ReconcileSuccessInterval = 120 * time.Second
FinalizerName = "featureflag.core.openfeature.dev/finalizer"
OpenFeatureAnnotationPath = "spec.template.metadata.annotations.openfeature.dev/openfeature.dev"
OpenFeatureAnnotationRoot = "openfeature.dev"
FlagdImagePullPolicy corev1.PullPolicy = "Always"
ClusterRoleBindingName string = "open-feature-operator-flagd-kubernetes-sync"
AllowKubernetesSyncAnnotation = "allowkubernetessync"
OpenFeatureAnnotationPrefix = "openfeature.dev"
PodOpenFeatureAnnotationPath = "metadata.annotations.openfeature.dev"
SourceConfigParam = "--sources"
ProbeReadiness = "/readyz"
ProbeLiveness = "/healthz"
ProbeInitialDelay = 5
FeatureFlagSourceAnnotation = "featureflagsource"
EnabledAnnotation = "enabled"
)
var ErrFlagdProxyNotReady = errors.New("flagd-proxy is not ready, deferring pod admission")
var ErrUnrecognizedSyncProvider = errors.New("unrecognized sync provider")
func FeatureFlagSourceIndex(o client.Object) []string {
deployment, ok := o.(*appsV1.Deployment)
if !ok {
return []string{
"false",
}
}
if deployment.Spec.Template.ObjectMeta.Annotations == nil {
return []string{
"false",
}
}
if _, ok := deployment.Spec.Template.ObjectMeta.Annotations[fmt.Sprintf("openfeature.dev/%s", FeatureFlagSourceAnnotation)]; ok {
return []string{
"true",
}
}
return []string{
"false",
}
}
func FindFlagConfig(ctx context.Context, c client.Client, namespace string, name string) (*api.FeatureFlag, error) {
ffConfig := &api.FeatureFlag{}
if err := c.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, ffConfig); err != nil {
return nil, err
}
return ffConfig, nil
}
// SharedOwnership returns true if any of the owner references match in the given slices
func SharedOwnership(ownerReferences1, ownerReferences2 []metav1.OwnerReference) bool {
for _, owner1 := range ownerReferences1 {
for _, owner2 := range ownerReferences2 {
if owner1.UID == owner2.UID {
return true
}
}
}
return false
}

View File

@ -1,248 +0,0 @@
package flagdproxy
import (
"context"
"fmt"
"reflect"
"github.com/go-logr/logr"
"github.com/open-feature/open-feature-operator/common/types"
appsV1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
)
const (
ManagedByAnnotationValue = "open-feature-operator"
FlagdProxyDeploymentName = "flagd-proxy"
FlagdProxyServiceAccountName = "open-feature-operator-flagd-proxy"
FlagdProxyServiceName = "flagd-proxy-svc"
operatorDeploymentName = "open-feature-operator-controller-manager"
)
type FlagdProxyHandler struct {
client.Client
config *FlagdProxyConfiguration
Log logr.Logger
}
type CreateUpdateFunc func(ctx context.Context, obj client.Object) error
type FlagdProxyConfiguration struct {
Port int
ManagementPort int
DebugLogging bool
Image string
Tag string
Namespace string
OperatorDeploymentName string
}
func NewFlagdProxyConfiguration(env types.EnvConfig) *FlagdProxyConfiguration {
return &FlagdProxyConfiguration{
Image: env.FlagdProxyImage,
Tag: env.FlagdProxyTag,
Namespace: env.PodNamespace,
OperatorDeploymentName: operatorDeploymentName,
Port: env.FlagdProxyPort,
ManagementPort: env.FlagdProxyManagementPort,
DebugLogging: env.FlagdProxyDebugLogging,
}
}
func NewFlagdProxyHandler(config *FlagdProxyConfiguration, client client.Client, logger logr.Logger) *FlagdProxyHandler {
return &FlagdProxyHandler{
config: config,
Client: client,
Log: logger,
}
}
func (f *FlagdProxyHandler) Config() *FlagdProxyConfiguration {
return f.config
}
func (f *FlagdProxyHandler) createObject(ctx context.Context, obj client.Object) error {
return f.Client.Create(ctx, obj)
}
func (f *FlagdProxyHandler) updateObject(ctx context.Context, obj client.Object) error {
return f.Client.Update(ctx, obj)
}
func (f *FlagdProxyHandler) HandleFlagdProxy(ctx context.Context) error {
exists, deployment, err := f.doesFlagdProxyExist(ctx)
if err != nil {
return err
}
ownerReference, err := f.getOwnerReference(ctx)
if err != nil {
return err
}
newDeployment := f.newFlagdProxyManifest(ownerReference)
newService := f.newFlagdProxyServiceManifest(ownerReference)
if !exists {
f.Log.Info("flagd-proxy Deployment does not exist, creating")
return f.deployFlagdProxy(ctx, f.createObject, newDeployment, newService)
}
// flagd-proxy exists, need to check if we should update it
if f.shouldUpdateFlagdProxy(deployment, newDeployment) {
f.Log.Info("flagd-proxy Deployment out of sync, updating")
return f.deployFlagdProxy(ctx, f.updateObject, newDeployment, newService)
}
f.Log.Info("flagd-proxy Deployment up-to-date")
return nil
}
func (f *FlagdProxyHandler) deployFlagdProxy(ctx context.Context, createUpdateFunc CreateUpdateFunc, deployment *appsV1.Deployment, service *corev1.Service) error {
f.Log.Info("deploying the flagd-proxy")
if err := createUpdateFunc(ctx, deployment); err != nil && !errors.IsAlreadyExists(err) {
return err
}
f.Log.Info("deploying the flagd-proxy service")
if err := createUpdateFunc(ctx, service); err != nil && !errors.IsAlreadyExists(err) {
return err
}
return nil
}
func (f *FlagdProxyHandler) newFlagdProxyServiceManifest(ownerReference *metav1.OwnerReference) *corev1.Service {
return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: FlagdProxyServiceName,
Namespace: f.config.Namespace,
OwnerReferences: []metav1.OwnerReference{*ownerReference},
},
Spec: corev1.ServiceSpec{
Selector: map[string]string{
"app.kubernetes.io/name": FlagdProxyDeploymentName,
"app.kubernetes.io/managed-by": ManagedByAnnotationValue,
},
Ports: []corev1.ServicePort{
{
Name: "flagd-proxy",
Port: int32(f.config.Port),
TargetPort: intstr.FromInt(f.config.Port),
},
},
},
}
}
func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReference *metav1.OwnerReference) *appsV1.Deployment {
replicas := int32(1)
args := []string{
"start",
"--management-port",
fmt.Sprintf("%d", f.config.ManagementPort),
}
if f.config.DebugLogging {
args = append(args, "--debug")
}
return &appsV1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: FlagdProxyDeploymentName,
Namespace: f.config.Namespace,
Labels: map[string]string{
"app": FlagdProxyDeploymentName,
"app.kubernetes.io/managed-by": ManagedByAnnotationValue,
"app.kubernetes.io/version": f.config.Tag,
},
OwnerReferences: []metav1.OwnerReference{*ownerReference},
},
Spec: appsV1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": FlagdProxyDeploymentName,
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": FlagdProxyDeploymentName,
"app.kubernetes.io/name": FlagdProxyDeploymentName,
"app.kubernetes.io/managed-by": ManagedByAnnotationValue,
"app.kubernetes.io/version": f.config.Tag,
},
},
Spec: corev1.PodSpec{
ServiceAccountName: FlagdProxyServiceAccountName,
Containers: []corev1.Container{
{
Image: fmt.Sprintf("%s:%s", f.config.Image, f.config.Tag),
Name: FlagdProxyDeploymentName,
Ports: []corev1.ContainerPort{
{
Name: "port",
ContainerPort: int32(f.config.Port),
},
{
Name: "management-port",
ContainerPort: int32(f.config.ManagementPort),
},
},
Args: args,
},
},
},
},
},
}
}
func (f *FlagdProxyHandler) doesFlagdProxyExist(ctx context.Context) (bool, *appsV1.Deployment, error) {
d := &appsV1.Deployment{}
err := f.Client.Get(ctx, client.ObjectKey{Name: FlagdProxyDeploymentName, Namespace: f.config.Namespace}, d)
if err != nil {
if errors.IsNotFound(err) {
// does not exist, is not ready, no error
return false, nil, nil
}
// does not exist, is not ready, is in error
return false, nil, err
}
return true, d, nil
}
func (f *FlagdProxyHandler) shouldUpdateFlagdProxy(old, new *appsV1.Deployment) bool {
if !isDeployedByOFO(old) {
f.Log.Info("flagd-proxy Deployment not managed by OFO")
return false
}
return !reflect.DeepEqual(old.Spec, new.Spec)
}
func (f *FlagdProxyHandler) getOperatorDeployment(ctx context.Context) (*appsV1.Deployment, error) {
d := &appsV1.Deployment{}
if err := f.Client.Get(ctx, client.ObjectKey{Name: f.config.OperatorDeploymentName, Namespace: f.config.Namespace}, d); err != nil {
return nil, fmt.Errorf("unable to fetch operator deployment: %w", err)
}
return d, nil
}
func (f *FlagdProxyHandler) getOwnerReference(ctx context.Context) (*metav1.OwnerReference, error) {
operatorDeployment, err := f.getOperatorDeployment(ctx)
if err != nil {
f.Log.Error(err, "unable to create owner reference for open-feature-operator")
return nil, err
}
return &metav1.OwnerReference{
UID: operatorDeployment.GetUID(),
Name: operatorDeployment.GetName(),
APIVersion: operatorDeployment.APIVersion,
Kind: operatorDeployment.Kind,
}, nil
}
func isDeployedByOFO(d *appsV1.Deployment) bool {
val, ok := d.Labels["app.kubernetes.io/managed-by"]
return ok && val == ManagedByAnnotationValue
}

View File

@ -1,24 +0,0 @@
package types
type EnvConfig struct {
PodNamespace string `envconfig:"POD_NAMESPACE" default:"open-feature-operator-system"`
FlagdProxyImage string `envconfig:"FLAGD_PROXY_IMAGE" default:"ghcr.io/open-feature/flagd-proxy"`
// renovate: datasource=github-tags depName=open-feature/flagd/flagd-proxy
FlagdProxyTag string `envconfig:"FLAGD_PROXY_TAG" default:"v0.5.0"`
FlagdProxyPort int `envconfig:"FLAGD_PROXY_PORT" default:"8015"`
FlagdProxyManagementPort int `envconfig:"FLAGD_PROXY_MANAGEMENT_PORT" default:"8016"`
FlagdProxyDebugLogging bool `envconfig:"FLAGD_PROXY_DEBUG_LOGGING" default:"false"`
SidecarEnvVarPrefix string `envconfig:"SIDECAR_ENV_VAR_PREFIX" default:"FLAGD"`
SidecarManagementPort int `envconfig:"SIDECAR_MANAGEMENT_PORT" default:"8014"`
SidecarPort int `envconfig:"SIDECAR_PORT" default:"8013"`
SidecarImage string `envconfig:"SIDECAR_IMAGE" default:"ghcr.io/open-feature/flagd"`
// renovate: datasource=github-tags depName=open-feature/flagd/flagd
SidecarTag string `envconfig:"SIDECAR_TAG" default:"v0.9.0"`
SidecarSocketPath string `envconfig:"SIDECAR_SOCKET_PATH" default:""`
SidecarEvaluator string `envconfig:"SIDECAR_EVALUATOR" default:"json"`
SidecarProviderArgs string `envconfig:"SIDECAR_PROVIDER_ARGS" default:""`
SidecarSyncProvider string `envconfig:"SIDECAR_SYNC_PROVIDER" default:"kubernetes"`
SidecarLogFormat string `envconfig:"SIDECAR_LOG_FORMAT" default:"json"`
SidecarProbesEnabled bool `envconfig:"SIDECAR_PROBES_ENABLED" default:"true"`
}

View File

@ -1,41 +0,0 @@
package utils
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_FeatureFlagId(t *testing.T) {
require.Equal(t, "namespace_name", FeatureFlagId("namespace", "name"))
}
func Test_FeatureFlagConfigMapKey(t *testing.T) {
require.Equal(t, "namespace_name.flagd.json", FeatureFlagConfigMapKey("namespace", "name"))
}
func Test_FalseVal(t *testing.T) {
f := false
require.Equal(t, &f, FalseVal())
}
func Test_TrueVal(t *testing.T) {
tt := true
require.Equal(t, &tt, TrueVal())
}
func Test_ContainsString(t *testing.T) {
slice := []string{"str1", "str2"}
require.True(t, ContainsString(slice, "str1"))
require.False(t, ContainsString(slice, "some"))
}
func Test_ParseAnnotations(t *testing.T) {
s1, s2 := ParseAnnotation("some/anno", "default")
require.Equal(t, "some", s1)
require.Equal(t, "anno", s2)
s1, s2 = ParseAnnotation("anno", "default")
require.Equal(t, "default", s1)
require.Equal(t, "anno", s2)
}

View File

@ -5,6 +5,9 @@ apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
labels:
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
spec:
selfSigned: {}
---
@ -12,12 +15,35 @@ apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
labels:
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
spec:
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
# SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
dnsNames:
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
- SERVICE_NAME.SERVICE_NAMESPACE.svc
- SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local
issuerRef:
kind: Issuer
name: selfsigned-issuer
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
---
# The following manifests contain a self-signed issuer CR and a metrics certificate CR.
# More document can be found at https://docs.cert-manager.io
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: metrics-certs # this name should match the one appeared in kustomizeconfig.yaml
labels:
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
spec:
dnsNames:
# SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
# replacements in the config/default/kustomization.yaml file.
- SERVICE_NAME.SERVICE_NAMESPACE.svc
- SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local
issuerRef:
kind: Issuer
name: selfsigned-issuer
secretName: metrics-server-cert

View File

@ -6,11 +6,3 @@ nameReference:
- kind: Certificate
group: cert-manager.io
path: spec/issuerRef/name
varReference:
- kind: Certificate
group: cert-manager.io
path: spec/commonName
- kind: Certificate
group: cert-manager.io
path: spec/dnsNames

View File

@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.10.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.16.5
name: featureflagconfigurations.core.openfeature.dev
spec:
group: core.openfeature.dev
@ -24,14 +23,19 @@ spec:
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'
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'
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
@ -57,15 +61,16 @@ spec:
C_IDENTIFIER.
type: string
value:
description: 'Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in
the container and any service environment variables. If
a variable cannot be resolved, the reference in the input
string will be unchanged. Double $$ are reduced to a single
$, which allows for escaping the $(VAR_NAME) syntax: i.e.
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless
of whether the variable exists or not. Defaults to "".'
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value.
@ -78,9 +83,13 @@ spec:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its
@ -91,11 +100,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: 'Selects a field of the pod: supports metadata.name,
metadata.namespace, `metadata.labels[''<KEY>'']`,
`metadata.annotations[''<KEY>'']`, spec.nodeName,
spec.serviceAccountName, status.hostIP, status.podIP,
status.podIPs.'
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath
@ -110,10 +117,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: 'Selects a resource of the container: only
resources limits and requests (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory
and requests.ephemeral-storage) are currently supported.'
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
@ -143,9 +149,13 @@ spec:
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key
@ -169,64 +179,47 @@ spec:
nullable: true
properties:
credentials:
description: "ObjectReference contains enough information to let
you inspect or modify the referred object. --- New uses of this
type are discouraged because of difficulty describing its usage
when embedded in APIs. 1. Ignored fields. It includes many
fields which are not generally honored. For instance, ResourceVersion
and FieldPath are both very rarely valid in actual usage. 2.
Invalid usage help. It is impossible to add specific help for
individual usage. In most embedded usages, there are particular
restrictions like, \"must refer only to types A and B\" or \"UID
not honored\" or \"name must be restricted\". Those cannot be
well described when embedded. 3. Inconsistent validation. Because
the usages are different, the validation rules are different
by usage, which makes it hard for users to predict what will
happen. 4. The fields are both imprecise and overly precise.
\ Kind is not a precise mapping to a URL. This can produce ambiguity
during interpretation and require a REST mapping. In most cases,
the dependency is on the group,resource tuple and the version
of the actual struct is irrelevant. 5. We cannot easily change
it. Because this type is embedded in many locations, updates
to this type will affect numerous schemas. Don't make new APIs
embed an underspecified API type they do not control. \n Instead
of using this type, create a locally provided and used type
that is well-focused on your reference. For example, ServiceReferences
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
."
description: ObjectReference contains enough information to let
you inspect or modify the referred object.
nullable: true
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a valid
JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen
only to have some well-defined way of referencing a part
of an object. TODO: this design is not final and this field
is subject to change in the future.'
description: |-
If referring to a piece of an object instead of an entire object, this string
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within a pod, this would take on a value like:
"spec.containers{name}" (where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to have some well-defined way of
referencing a part of an object.
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
description: |-
Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
description: |-
Specific resourceVersion to which this reference is made, if any.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
description: |-
UID of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
type: string
type: object
x-kubernetes-map-type: atomic
@ -276,14 +269,19 @@ spec:
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'
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'
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
@ -338,15 +336,16 @@ spec:
C_IDENTIFIER.
type: string
value:
description: 'Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in
the container and any service environment variables. If
a variable cannot be resolved, the reference in the input
string will be unchanged. Double $$ are reduced to a single
$, which allows for escaping the $(VAR_NAME) syntax: i.e.
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless
of whether the variable exists or not. Defaults to "".'
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value.
@ -359,9 +358,13 @@ spec:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its
@ -372,11 +375,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: 'Selects a field of the pod: supports metadata.name,
metadata.namespace, `metadata.labels[''<KEY>'']`,
`metadata.annotations[''<KEY>'']`, spec.nodeName,
spec.serviceAccountName, status.hostIP, status.podIP,
status.podIPs.'
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath
@ -391,10 +392,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: 'Selects a resource of the container: only
resources limits and requests (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory
and requests.ephemeral-storage) are currently supported.'
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
@ -424,9 +424,13 @@ spec:
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key
@ -447,18 +451,28 @@ spec:
operator sidecar-cpu-* and sidecar-ram-* flags.
properties:
claims:
description: "Claims lists the names of resources, defined in
spec.resourceClaims, that are used by this container. \n This
is an alpha field and requires enabling the DynamicResourceAllocation
feature gate. \n This field is immutable. It can only be set
for containers."
description: |-
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
This is an alpha field and requires enabling the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
items:
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
properties:
name:
description: Name must match the name of one entry in pod.spec.resourceClaims
of the Pod where this field is used. It makes that resource
available inside a container.
description: |-
Name must match the name of one entry in pod.spec.resourceClaims of
the Pod where this field is used. It makes that resource available
inside a container.
type: string
request:
description: |-
Request is the name chosen for a request in the referenced claim.
If empty, everything from the claim is made available, otherwise
only the result of this request.
type: string
required:
- name
@ -474,8 +488,9 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount of compute resources
allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Limits describes the maximum amount of compute resources allowed.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
requests:
additionalProperties:
@ -484,10 +499,11 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum amount of compute
resources required. If Requests is omitted for a container,
it defaults to Limits if that is explicitly specified, otherwise
to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Requests describes the minimum amount of compute resources required.
If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
otherwise to an implementation-defined value. Requests cannot exceed Limits.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
type: object
serviceProvider:
@ -495,64 +511,47 @@ spec:
nullable: true
properties:
credentials:
description: "ObjectReference contains enough information to let
you inspect or modify the referred object. --- New uses of this
type are discouraged because of difficulty describing its usage
when embedded in APIs. 1. Ignored fields. It includes many
fields which are not generally honored. For instance, ResourceVersion
and FieldPath are both very rarely valid in actual usage. 2.
Invalid usage help. It is impossible to add specific help for
individual usage. In most embedded usages, there are particular
restrictions like, \"must refer only to types A and B\" or \"UID
not honored\" or \"name must be restricted\". Those cannot be
well described when embedded. 3. Inconsistent validation. Because
the usages are different, the validation rules are different
by usage, which makes it hard for users to predict what will
happen. 4. The fields are both imprecise and overly precise.
\ Kind is not a precise mapping to a URL. This can produce ambiguity
during interpretation and require a REST mapping. In most cases,
the dependency is on the group,resource tuple and the version
of the actual struct is irrelevant. 5. We cannot easily change
it. Because this type is embedded in many locations, updates
to this type will affect numerous schemas. Don't make new APIs
embed an underspecified API type they do not control. \n Instead
of using this type, create a locally provided and used type
that is well-focused on your reference. For example, ServiceReferences
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
."
description: ObjectReference contains enough information to let
you inspect or modify the referred object.
nullable: true
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead
of an entire object, this string should contain a valid
JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen
only to have some well-defined way of referencing a part
of an object. TODO: this design is not final and this field
is subject to change in the future.'
description: |-
If referring to a piece of an object instead of an entire object, this string
should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within a pod, this would take on a value like:
"spec.containers{name}" (where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]" (container with
index 2 in this pod). This syntax is chosen only to have some well-defined way of
referencing a part of an object.
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
description: |-
Name of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
description: |-
Namespace of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
description: |-
Specific resourceVersion to which this reference is made, if any.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
description: |-
UID of the referent.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids
type: string
type: object
x-kubernetes-map-type: atomic

View File

@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.10.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.16.5
name: featureflags.core.openfeature.dev
spec:
group: core.openfeature.dev
@ -23,14 +22,19 @@ spec:
description: FeatureFlag is the Schema for the featureflags 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'
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'
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

View File

@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.10.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.16.5
name: featureflagsources.core.openfeature.dev
spec:
group: core.openfeature.dev
@ -23,14 +22,19 @@ spec:
description: FeatureFlagSource is the Schema for the FeatureFlagSources 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'
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'
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
@ -45,13 +49,14 @@ spec:
description: DefaultSyncProvider defines the default sync provider
type: string
envVarPrefix:
default: FLAGD
description: EnvVarPrefix defines the prefix to be applied to all
environment variables applied to the sidecar, default FLAGD
type: string
envVars:
description: EnvVars define the env vars to be applied to the sidecar,
any env vars in FeatureFlag CRs are added at the lowest index, all
values will have the EnvVarPrefix applied, default FLAGD
description: |-
EnvVars define the env vars to be applied to the sidecar, any env vars in FeatureFlag CRs
are added at the lowest index, all values will have the EnvVarPrefix applied, default FLAGD
items:
description: EnvVar represents an environment variable present in
a Container.
@ -60,15 +65,16 @@ spec:
description: Name of the environment variable. Must be a C_IDENTIFIER.
type: string
value:
description: 'Variable references $(VAR_NAME) are expanded using
the previously defined environment variables in the container
and any service environment variables. If a variable cannot
be resolved, the reference in the input string will be unchanged.
Double $$ are reduced to a single $, which allows for escaping
the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the
string literal "$(VAR_NAME)". Escaped references will never
be expanded, regardless of whether the variable exists or
not. Defaults to "".'
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value. Cannot
@ -81,8 +87,13 @@ spec:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its key
@ -93,10 +104,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: 'Selects a field of the pod: supports metadata.name,
metadata.namespace, `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`,
spec.nodeName, spec.serviceAccountName, status.hostIP,
status.podIP, status.podIPs.'
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath is
@ -111,10 +121,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: 'Selects a resource of the container: only
resources limits and requests (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory
and requests.ephemeral-storage) are currently supported.'
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
@ -143,8 +152,13 @@ spec:
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must
@ -160,13 +174,16 @@ spec:
type: object
type: array
evaluator:
default: json
description: Evaluator sets an evaluator, defaults to 'json'
type: string
logFormat:
default: json
description: LogFormat allows for the sidecar log format to be overridden,
defaults to 'json'
type: string
managementPort:
default: 8014
description: ManagemetPort defines the port to serve management on,
defaults to 8014
format: int32
@ -176,6 +193,7 @@ spec:
flag of flagd sidecar. Default false (disabled).
type: string
port:
default: 8013
description: Port defines the port to listen on, defaults to 8013
format: int32
type: integer
@ -188,18 +206,28 @@ spec:
operator sidecar-cpu-* and sidecar-ram-* flags.
properties:
claims:
description: "Claims lists the names of resources, defined in
spec.resourceClaims, that are used by this container. \n This
is an alpha field and requires enabling the DynamicResourceAllocation
feature gate. \n This field is immutable. It can only be set
for containers."
description: |-
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
This is an alpha field and requires enabling the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
items:
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
properties:
name:
description: Name must match the name of one entry in pod.spec.resourceClaims
of the Pod where this field is used. It makes that resource
available inside a container.
description: |-
Name must match the name of one entry in pod.spec.resourceClaims of
the Pod where this field is used. It makes that resource available
inside a container.
type: string
request:
description: |-
Request is the name chosen for a request in the referenced claim.
If empty, everything from the claim is made available, otherwise
only the result of this request.
type: string
required:
- name
@ -215,8 +243,9 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount of compute resources
allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Limits describes the maximum amount of compute resources allowed.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
requests:
additionalProperties:
@ -225,16 +254,17 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum amount of compute
resources required. If Requests is omitted for a container,
it defaults to Limits if that is explicitly specified, otherwise
to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Requests describes the minimum amount of compute resources required.
If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
otherwise to an implementation-defined value. Requests cannot exceed Limits.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
type: object
rolloutOnChange:
description: RolloutOnChange dictates whether annotated deployments
will be restarted when configuration changes are detected in this
CR, defaults to false
description: |-
RolloutOnChange dictates whether annotated deployments will be restarted when configuration changes are
detected in this CR, defaults to false
type: boolean
socketPath:
description: SocketPath defines the unix socket path to listen on
@ -252,6 +282,11 @@ spec:
description: HttpSyncBearerToken is a bearer token. Used by
http(s) sync provider only
type: string
interval:
description: Interval is a flag configuration interval in seconds
used by http provider
format: int32
type: integer
provider:
description: Provider type - kubernetes, http(s), grpc(s) or
file

View File

@ -0,0 +1,324 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.5
name: flagds.core.openfeature.dev
spec:
group: core.openfeature.dev
names:
kind: Flagd
listKind: FlagdList
plural: flagds
singular: flagd
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: Flagd is the Schema for the flagds 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: FlagdSpec defines the desired state of Flagd
properties:
featureFlagSource:
description: |-
FeatureFlagSource references to a FeatureFlagSource from which the created flagd instance retrieves
the feature flag configurations
type: string
gatewayApiRoutes:
description: GatewayApiRoutes
properties:
annotations:
additionalProperties:
type: string
description: Annotations to be added to the Gateway API routes
type: object
enabled:
description: Enabled enables/disables the Gateway API routes for
flagd
type: boolean
hosts:
description: |-
Hosts list of hosts to be added to the ingress.
Empty string corresponds to rule with no host.
items:
type: string
type: array
parentRefs:
description: |-
ParentRefs references the resources (usually Gateways) that the Routes should
be attached to.
items:
description: |-
ParentReference identifies an API object (usually a Gateway) that can be considered
a parent of this resource (usually a route). There are two kinds of parent resources
with "Core" support:
* Gateway (Gateway conformance profile)
* Service (Mesh conformance profile, ClusterIP Services only)
This API may be extended in the future to support additional kinds of parent
resources.
The API object must be valid in the cluster; the Group and Kind must
be registered in the cluster for this reference to be valid.
properties:
group:
default: gateway.networking.k8s.io
description: |-
Group is the group of the referent.
When unspecified, "gateway.networking.k8s.io" is inferred.
To set the core API group (such as for a "Service" kind referent),
Group must be explicitly set to "" (empty string).
Support: Core
maxLength: 253
pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
kind:
default: Gateway
description: |-
Kind is kind of the referent.
There are two kinds of parent resources with "Core" support:
* Gateway (Gateway conformance profile)
* Service (Mesh conformance profile, ClusterIP Services only)
Support for other resources is Implementation-Specific.
maxLength: 63
minLength: 1
pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$
type: string
name:
description: |-
Name is the name of the referent.
Support: Core
maxLength: 253
minLength: 1
type: string
namespace:
description: |-
Namespace is the namespace of the referent. When unspecified, this refers
to the local namespace of the Route.
Note that there are specific rules for ParentRefs which cross namespace
boundaries. Cross-namespace references are only valid if they are explicitly
allowed by something in the namespace they are referring to. For example:
Gateway has the AllowedRoutes field, and ReferenceGrant provides a
generic way to enable any other kind of cross-namespace reference.
<gateway:experimental:description>
ParentRefs from a Route to a Service in the same namespace are "producer"
routes, which apply default routing rules to inbound connections from
any namespace to the Service.
ParentRefs from a Route to a Service in a different namespace are
"consumer" routes, and these routing rules are only applied to outbound
connections originating from the same namespace as the Route, for which
the intended destination of the connections are a Service targeted as a
ParentRef of the Route.
</gateway:experimental:description>
Support: Core
maxLength: 63
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
type: string
port:
description: |-
Port is the network port this Route targets. It can be interpreted
differently based on the type of parent resource.
When the parent resource is a Gateway, this targets all listeners
listening on the specified port that also support this kind of Route(and
select this Route). It's not recommended to set `Port` unless the
networking behaviors specified in a Route must apply to a specific port
as opposed to a listener(s) whose port(s) may be changed. When both Port
and SectionName are specified, the name and port of the selected listener
must match both specified values.
<gateway:experimental:description>
When the parent resource is a Service, this targets a specific port in the
Service spec. When both Port (experimental) and SectionName are specified,
the name and port of the selected port must match both specified values.
</gateway:experimental:description>
Implementations MAY choose to support other parent resources.
Implementations supporting other types of parent resources MUST clearly
document how/if Port is interpreted.
For the purpose of status, an attachment is considered successful as
long as the parent resource accepts it partially. For example, Gateway
listeners can restrict which Routes can attach to them by Route kind,
namespace, or hostname. If 1 of 2 Gateway listeners accept attachment
from the referencing Route, the Route MUST be considered successfully
attached. If no Gateway listeners accept attachment from this Route,
the Route MUST be considered detached from the Gateway.
Support: Extended
format: int32
maximum: 65535
minimum: 1
type: integer
sectionName:
description: |-
SectionName is the name of a section within the target resource. In the
following resources, SectionName is interpreted as the following:
* Gateway: Listener name. When both Port (experimental) and SectionName
are specified, the name and port of the selected listener must match
both specified values.
* Service: Port name. When both Port (experimental) and SectionName
are specified, the name and port of the selected listener must match
both specified values.
Implementations MAY choose to support attaching Routes to other resources.
If that is the case, they MUST clearly document how SectionName is
interpreted.
When unspecified (empty string), this will reference the entire resource.
For the purpose of status, an attachment is considered successful if at
least one section in the parent resource accepts it. For example, Gateway
listeners can restrict which Routes can attach to them by Route kind,
namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from
the referencing Route, the Route MUST be considered successfully
attached. If no Gateway listeners accept attachment from this Route, the
Route MUST be considered detached from the Gateway.
Support: Core
maxLength: 253
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
required:
- name
type: object
type: array
required:
- parentRefs
type: object
ingress:
description: Ingress
properties:
annotations:
additionalProperties:
type: string
description: Annotations the annotations to be added to the ingress
type: object
enabled:
description: Enabled enables/disables the ingress for flagd
type: boolean
flagdPath:
description: |-
FlagdPath is the path to be used for accessing the flagd flag evaluation API
Default: /flagd.evaluation.v1.Service
type: string
hosts:
description: |-
Hosts list of hosts to be added to the ingress.
Empty string corresponds to rule with no host.
items:
type: string
type: array
ingressClassName:
description: IngressClassName defines the name if the ingress
class to be used for flagd
type: string
ofrepPath:
description: |-
OFREPPath is the path to be used for accessing the OFREP API
Default: /ofrep
type: string
pathType:
description: PathType is the path type to be used for the ingress
rules
type: string
syncPath:
description: |-
SyncPath is the path to be used for accessing the sync API
Default: /flagd.sync.v1.Service
type: string
tls:
description: TLS configuration for the ingress
items:
description: IngressTLS describes the transport layer security
associated with an ingress.
properties:
hosts:
description: |-
hosts is a list of hosts included in the TLS certificate. The values in
this list must match the name/s used in the tlsSecret. Defaults to the
wildcard host setting for the loadbalancer controller fulfilling this
Ingress, if left unspecified.
items:
type: string
type: array
x-kubernetes-list-type: atomic
secretName:
description: |-
secretName is the name of the secret used to terminate TLS traffic on
port 443. Field is left optional to allow TLS routing based on SNI
hostname alone. If the SNI host in a listener conflicts with the "Host"
header field used by an IngressRule, the SNI host is used for termination
and value of the "Host" header is used for routing.
type: string
type: object
type: array
required:
- hosts
type: object
replicas:
default: 1
description: |-
Replicas defines the number of replicas to create for the service.
Default: 1
format: int32
type: integer
serviceAccountName:
description: ServiceAccountName the service account name for the flagd
deployment
type: string
serviceType:
default: ClusterIP
description: |-
ServiceType represents the type of Service to create.
Must be one of: ClusterIP, NodePort, LoadBalancer, and ExternalName.
Default: ClusterIP
enum:
- ClusterIP
- NodePort
- LoadBalancer
- ExternalName
type: string
required:
- featureFlagSource
type: object
status:
description: FlagdStatus defines the observed state of Flagd
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.10.0
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.16.5
name: flagsourceconfigurations.core.openfeature.dev
spec:
group: core.openfeature.dev
@ -24,14 +23,19 @@ spec:
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'
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'
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
@ -51,9 +55,9 @@ spec:
environment variables applied to the sidecar, default FLAGD
type: string
envVars:
description: EnvVars define the env vars to be applied to the sidecar,
any env vars in FeatureFlagConfiguration CRs are added at the lowest
index, all values will have the EnvVarPrefix applied
description: |-
EnvVars define the env vars to be applied to the sidecar, any env vars in FeatureFlagConfiguration CRs
are added at the lowest index, all values will have the EnvVarPrefix applied
items:
description: EnvVar represents an environment variable present in
a Container.
@ -62,15 +66,16 @@ spec:
description: Name of the environment variable. Must be a C_IDENTIFIER.
type: string
value:
description: 'Variable references $(VAR_NAME) are expanded using
the previously defined environment variables in the container
and any service environment variables. If a variable cannot
be resolved, the reference in the input string will be unchanged.
Double $$ are reduced to a single $, which allows for escaping
the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the
string literal "$(VAR_NAME)". Escaped references will never
be expanded, regardless of whether the variable exists or
not. Defaults to "".'
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value. Cannot
@ -83,8 +88,13 @@ spec:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its key
@ -95,10 +105,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: 'Selects a field of the pod: supports metadata.name,
metadata.namespace, `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`,
spec.nodeName, spec.serviceAccountName, status.hostIP,
status.podIP, status.podIPs.'
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath is
@ -113,10 +122,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: 'Selects a resource of the container: only
resources limits and requests (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory
and requests.ephemeral-storage) are currently supported.'
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
@ -145,8 +153,13 @@ spec:
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must
@ -194,18 +207,28 @@ spec:
operator sidecar-cpu-* and sidecar-ram-* flags.
properties:
claims:
description: "Claims lists the names of resources, defined in
spec.resourceClaims, that are used by this container. \n This
is an alpha field and requires enabling the DynamicResourceAllocation
feature gate. \n This field is immutable. It can only be set
for containers."
description: |-
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
This is an alpha field and requires enabling the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
items:
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
properties:
name:
description: Name must match the name of one entry in pod.spec.resourceClaims
of the Pod where this field is used. It makes that resource
available inside a container.
description: |-
Name must match the name of one entry in pod.spec.resourceClaims of
the Pod where this field is used. It makes that resource available
inside a container.
type: string
request:
description: |-
Request is the name chosen for a request in the referenced claim.
If empty, everything from the claim is made available, otherwise
only the result of this request.
type: string
required:
- name
@ -221,8 +244,9 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount of compute resources
allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Limits describes the maximum amount of compute resources allowed.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
requests:
additionalProperties:
@ -231,16 +255,17 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum amount of compute
resources required. If Requests is omitted for a container,
it defaults to Limits if that is explicitly specified, otherwise
to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Requests describes the minimum amount of compute resources required.
If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
otherwise to an implementation-defined value. Requests cannot exceed Limits.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
type: object
rolloutOnChange:
description: RolloutOnChange dictates whether annotated deployments
will be restarted when configuration changes are detected in this
CR, defaults to false
description: |-
RolloutOnChange dictates whether annotated deployments will be restarted when configuration changes are
detected in this CR, defaults to false
type: boolean
socketPath:
description: SocketPath defines the unix socket path to listen on
@ -310,14 +335,19 @@ spec:
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'
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'
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
@ -386,14 +416,19 @@ spec:
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'
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'
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
@ -413,9 +448,9 @@ spec:
environment variables applied to the sidecar, default FLAGD
type: string
envVars:
description: EnvVars define the env vars to be applied to the sidecar,
any env vars in FeatureFlagConfiguration CRs are added at the lowest
index, all values will have the EnvVarPrefix applied, default FLAGD
description: |-
EnvVars define the env vars to be applied to the sidecar, any env vars in FeatureFlagConfiguration CRs
are added at the lowest index, all values will have the EnvVarPrefix applied, default FLAGD
items:
description: EnvVar represents an environment variable present in
a Container.
@ -424,15 +459,16 @@ spec:
description: Name of the environment variable. Must be a C_IDENTIFIER.
type: string
value:
description: 'Variable references $(VAR_NAME) are expanded using
the previously defined environment variables in the container
and any service environment variables. If a variable cannot
be resolved, the reference in the input string will be unchanged.
Double $$ are reduced to a single $, which allows for escaping
the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the
string literal "$(VAR_NAME)". Escaped references will never
be expanded, regardless of whether the variable exists or
not. Defaults to "".'
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value. Cannot
@ -445,8 +481,13 @@ spec:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its key
@ -457,10 +498,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: 'Selects a field of the pod: supports metadata.name,
metadata.namespace, `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`,
spec.nodeName, spec.serviceAccountName, status.hostIP,
status.podIP, status.podIPs.'
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath is
@ -475,10 +515,9 @@ spec:
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: 'Selects a resource of the container: only
resources limits and requests (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory
and requests.ephemeral-storage) are currently supported.'
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
@ -507,8 +546,13 @@ spec:
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must
@ -556,18 +600,28 @@ spec:
operator sidecar-cpu-* and sidecar-ram-* flags.
properties:
claims:
description: "Claims lists the names of resources, defined in
spec.resourceClaims, that are used by this container. \n This
is an alpha field and requires enabling the DynamicResourceAllocation
feature gate. \n This field is immutable. It can only be set
for containers."
description: |-
Claims lists the names of resources, defined in spec.resourceClaims,
that are used by this container.
This is an alpha field and requires enabling the
DynamicResourceAllocation feature gate.
This field is immutable. It can only be set for containers.
items:
description: ResourceClaim references one entry in PodSpec.ResourceClaims.
properties:
name:
description: Name must match the name of one entry in pod.spec.resourceClaims
of the Pod where this field is used. It makes that resource
available inside a container.
description: |-
Name must match the name of one entry in pod.spec.resourceClaims of
the Pod where this field is used. It makes that resource available
inside a container.
type: string
request:
description: |-
Request is the name chosen for a request in the referenced claim.
If empty, everything from the claim is made available, otherwise
only the result of this request.
type: string
required:
- name
@ -583,8 +637,9 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Limits describes the maximum amount of compute resources
allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Limits describes the maximum amount of compute resources allowed.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
requests:
additionalProperties:
@ -593,16 +648,17 @@ spec:
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: 'Requests describes the minimum amount of compute
resources required. If Requests is omitted for a container,
it defaults to Limits if that is explicitly specified, otherwise
to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
description: |-
Requests describes the minimum amount of compute resources required.
If Requests is omitted for a container, it defaults to Limits if that is explicitly specified,
otherwise to an implementation-defined value. Requests cannot exceed Limits.
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
type: object
rolloutOnChange:
description: RolloutOnChange dictates whether annotated deployments
will be restarted when configuration changes are detected in this
CR, defaults to false
description: |-
RolloutOnChange dictates whether annotated deployments will be restarted when configuration changes are
detected in this CR, defaults to false
type: boolean
socketPath:
description: SocketPath defines the unix socket path to listen on

View File

@ -0,0 +1,206 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.5
name: inprocessconfigurations.core.openfeature.dev
spec:
group: core.openfeature.dev
names:
kind: InProcessConfiguration
listKind: InProcessConfigurationList
plural: inprocessconfigurations
singular: inprocessconfiguration
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: InProcessConfiguration is the Schema for the inprocesconfigurations
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: InProcessConfigurationSpec defines the desired state of InProcessConfiguration
properties:
cache:
default: lru
description: Cache
pattern: ^(lru|disabled)$
type: string
cacheMaxSize:
default: 1000
description: CacheMaxSize
type: integer
envVarPrefix:
default: FLAGD
description: EnvVarPrefix defines the prefix to be applied to all
environment variables applied to the sidecar, default FLAGD
type: string
envVars:
description: EnvVars
items:
description: EnvVar represents an environment variable present in
a Container.
properties:
name:
description: Name of the environment variable. Must be a C_IDENTIFIER.
type: string
value:
description: |-
Variable references $(VAR_NAME) are expanded
using the previously defined environment variables in the container and
any service environment variables. If a variable cannot be resolved,
the reference in the input string will be unchanged. Double $$ are reduced
to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e.
"$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)".
Escaped references will never be expanded, regardless of whether the variable
exists or not.
Defaults to "".
type: string
valueFrom:
description: Source for the environment variable's value. Cannot
be used if value is not empty.
properties:
configMapKeyRef:
description: Selects a key of a ConfigMap.
properties:
key:
description: The key to select.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the ConfigMap or its key
must be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
fieldRef:
description: |-
Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`,
spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs.
properties:
apiVersion:
description: Version of the schema the FieldPath is
written in terms of, defaults to "v1".
type: string
fieldPath:
description: Path of the field to select in the specified
API version.
type: string
required:
- fieldPath
type: object
x-kubernetes-map-type: atomic
resourceFieldRef:
description: |-
Selects a resource of the container: only resources limits and requests
(limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported.
properties:
containerName:
description: 'Container name: required for volumes,
optional for env vars'
type: string
divisor:
anyOf:
- type: integer
- type: string
description: Specifies the output format of the exposed
resources, defaults to "1"
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
resource:
description: 'Required: resource to select'
type: string
required:
- resource
type: object
x-kubernetes-map-type: atomic
secretKeyRef:
description: Selects a key of a secret in the pod's namespace
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
default: ""
description: |-
Name of the referent.
This field is effectively required, but due to backwards compatibility is
allowed to be empty. Instances of this type with an empty value here are
almost certainly wrong.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
x-kubernetes-map-type: atomic
type: object
required:
- name
type: object
type: array
host:
default: localhost
description: Host
type: string
offlineFlagSourcePath:
description: OfflineFlagSourcePath
type: string
port:
default: 8015
description: Port defines the port to listen on, defaults to 8015
format: int32
type: integer
selector:
description: Selector
type: string
socketPath:
description: SocketPath defines the unix socket path to listen on
type: string
tls:
default: false
description: TLS
type: boolean
type: object
status:
description: InProcessConfigurationStatus defines the observed state of
InProcessConfiguration
type: object
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -4,21 +4,19 @@
resources:
- bases/core.openfeature.dev_featureflags.yaml
- bases/core.openfeature.dev_featureflagsources.yaml
- bases/core.openfeature.dev_flagds.yaml
- bases/core.openfeature.dev_inprocessconfigurations.yaml
#+kubebuilder:scaffold:crdkustomizeresource
patchesStrategicMerge:
patches:
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
#- patches/webhook_in_featureflags.yaml
#- patches/webhook_in_featureflagsources.yaml
#- patches/webhook_in_flagds.yaml
#- patches/webhook_in_inprocessconfigurations.yaml
#+kubebuilder:scaffold:crdkustomizewebhookpatch
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
# patches here are for enabling the CA injection for each CRD
#- patches/cainjection_in_featureflags.yaml
#- patches/cainjection_in_featureflagsources.yaml
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
# the following config is for teaching kustomize how to do kustomization for CRDs.
configurations:
- kustomizeconfig.yaml

View File

@ -1,19 +1,19 @@
# This file is for teaching kustomize how to substitute name and namespace reference in CRD
nameReference:
- kind: Service
version: v1
fieldSpecs:
- kind: Service
version: v1
fieldSpecs:
- kind: CustomResourceDefinition
version: v1
group: apiextensions.k8s.io
path: spec/conversion/webhook/clientConfig/service/name
namespace:
- kind: CustomResourceDefinition
version: v1
group: apiextensions.k8s.io
path: spec/conversion/webhook/clientConfig/service/name
namespace:
- kind: CustomResourceDefinition
version: v1
group: apiextensions.k8s.io
path: spec/conversion/webhook/clientConfig/service/namespace
create: false
path: spec/conversion/webhook/clientConfig/service/namespace
create: false
varReference:
- path: metadata/annotations
- path: metadata/annotations

View File

@ -1,7 +0,0 @@
# The following patch adds a directive for certmanager to inject CA into the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: featureflags.core.openfeature.dev

View File

@ -1,7 +0,0 @@
# The following patch adds a directive for certmanager to inject CA into the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
name: featureflagsources.core.openfeature.dev

View File

@ -0,0 +1,16 @@
# The following patch enables a conversion webhook for the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: flagds.core.openfeature.dev
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: system
name: webhook-service
path: /convert
conversionReviewVersions:
- v1

View File

@ -0,0 +1,16 @@
# The following patch enables a conversion webhook for the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: inprocessconfigurations.core.openfeature.dev
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: system
name: webhook-service
path: /convert
conversionReviewVersions:
- v1

View File

@ -0,0 +1,30 @@
# This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs.
# Add the volumeMount for the metrics-server certs
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
mountPath: /tmp/k8s-metrics-server/metrics-certs
name: metrics-certs
readOnly: true
# Add the --metrics-cert-path argument for the metrics server
- op: add
path: /spec/template/spec/containers/0/args/-
value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs
# Add the metrics-server certs volume configuration
- op: add
path: /spec/template/spec/volumes/-
value:
name: metrics-certs
secret:
secretName: metrics-server-cert
optional: false
items:
- key: ca.crt
path: ca.crt
- key: tls.crt
path: tls.crt
- key: tls.key
path: tls.key

View File

@ -12,63 +12,206 @@ namePrefix: open-feature-operator-
#commonLabels:
# someName: someValue
bases:
resources:
- ../crd
- ../rbac
- ../manager
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
- ../webhook
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
- ../certmanager
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
#- ../prometheus
patchesStrategicMerge:
# Protect the /metrics endpoint by putting it behind auth.
# If you want your controller-manager to expose the /metrics
# endpoint w/o any authn/z, please comment the following line.
- manager_auth_proxy_patch.yaml
# [NETWORK POLICY] Protect the /metrics endpoint and Webhook Server with NetworkPolicy.
# Only Pod(s) running a namespace labeled with 'metrics: enabled' will be able to gather the metrics.
# Only CR(s) which requires webhooks and are applied on namespaces labeled with 'webhooks: enabled' will
# be able to communicate with the Webhook Server.
#- ../network-policy
patches:
# Mount the controller config file for loading manager configurations
# through a ComponentConfig type
#- manager_config_patch.yaml
# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443.
# More info: https://book.kubebuilder.io/reference/metrics
- path: manager_metrics_patch.yaml
target:
kind: Deployment
# Uncomment the patches line if you enable Metrics and CertManager
# [METRICS-WITH-CERTS] To enable metrics protected with certManager, uncomment the following line.
# This patch will protect the metrics with certManager self-signed certs.
- path: cert_metrics_manager_patch.yaml
target:
kind: Deployment
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
- manager_webhook_patch.yaml
- path: manager_webhook_patch.yaml
target:
kind: Deployment
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
# 'CERTMANAGER' needs to be enabled to use ca injection
- webhookcainjection_patch.yaml
# the following config is for teaching kustomize how to do var substitution
vars:
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix.
- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR
objref:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # this name should match the one in certificate.yaml
fieldref:
fieldpath: metadata.namespace
- name: CERTIFICATE_NAME
objref:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # this name should match the one in certificate.yaml
- name: SERVICE_NAMESPACE # namespace of the service
objref:
kind: Service
version: v1
name: webhook-service
fieldref:
fieldpath: metadata.namespace
- name: SERVICE_NAME
objref:
kind: Service
version: v1
name: webhook-service
# Uncomment the following replacements to add the cert-manager CA injection annotations
replacements:
- source: # Uncomment the following block to enable certificates for metrics
kind: Service
version: v1
name: controller-manager-metrics-service
fieldPath: metadata.name
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: metrics-certs
fieldPaths:
- spec.dnsNames.0
- spec.dnsNames.1
options:
delimiter: '.'
index: 0
create: true
- source:
kind: Service
version: v1
name: controller-manager-metrics-service
fieldPath: metadata.namespace
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: metrics-certs
fieldPaths:
- spec.dnsNames.0
- spec.dnsNames.1
options:
delimiter: '.'
index: 1
create: true
- source: # Uncomment the following block if you have any webhook
kind: Service
version: v1
name: webhook-service
fieldPath: .metadata.name # Name of the service
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert
fieldPaths:
- .spec.dnsNames.0
- .spec.dnsNames.1
options:
delimiter: '.'
index: 0
create: true
- source:
kind: Service
version: v1
name: webhook-service
fieldPath: .metadata.namespace # Namespace of the service
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert
fieldPaths:
- .spec.dnsNames.0
- .spec.dnsNames.1
options:
delimiter: '.'
index: 1
create: true
- source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation)
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert # This name should match the one in certificate.yaml
fieldPath: .metadata.namespace # Namespace of the certificate CR
targets:
- select:
kind: ValidatingWebhookConfiguration
fieldPaths:
- .metadata.annotations.[cert-manager.io/inject-ca-from]
options:
delimiter: '/'
index: 0
create: true
- source:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert
fieldPath: .metadata.name
targets:
- select:
kind: ValidatingWebhookConfiguration
fieldPaths:
- .metadata.annotations.[cert-manager.io/inject-ca-from]
options:
delimiter: '/'
index: 1
create: true
- source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting )
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert
fieldPath: .metadata.namespace # Namespace of the certificate CR
targets:
- select:
kind: MutatingWebhookConfiguration
fieldPaths:
- .metadata.annotations.[cert-manager.io/inject-ca-from]
options:
delimiter: '/'
index: 0
create: true
- source:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert
fieldPath: .metadata.name
targets:
- select:
kind: MutatingWebhookConfiguration
fieldPaths:
- .metadata.annotations.[cert-manager.io/inject-ca-from]
options:
delimiter: '/'
index: 1
create: true
# - source: # Uncomment the following block if you have a ConversionWebhook (--conversion)
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert
# fieldPath: .metadata.namespace # Namespace of the certificate CR
# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# +kubebuilder:scaffold:crdkustomizecainjectionns
# - source:
# kind: Certificate
# group: cert-manager.io
# version: v1
# name: serving-cert
# fieldPath: .metadata.name
# targets: # Do not remove or uncomment the following scaffold marker; required to generate code for target CRD.
# +kubebuilder:scaffold:crdkustomizecainjectionname

View File

@ -1,42 +0,0 @@
# This patch inject a sidecar container which is a HTTP proxy for the
# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: kube-rbac-proxy
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.14.0
args:
- "--secure-listen-address=0.0.0.0:8443"
- "--upstream=http://127.0.0.1:8080/"
- "--logtostderr=true"
- "--v=0"
ports:
- containerPort: 8443
protocol: TCP
name: https
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 5m
memory: 64Mi
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
- name: manager
args:
- "--health-probe-bind-address=:8081"
- "--metrics-bind-address=127.0.0.1:8080"
- "--leader-elect"
- "--sidecar-cpu-limit=0.5" # cores
- "--sidecar-ram-limit=64M"
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true

View File

@ -0,0 +1,4 @@
# This patch adds the args to allow exposing the metrics endpoint using HTTPS
- op: add
path: /spec/template/spec/containers/0/args/0
value: --metrics-bind-address=:8443

View File

@ -1,23 +1,31 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
volumes:
- name: cert
secret:
defaultMode: 420
secretName: webhook-server-cert
# This patch ensures the webhook certificates are properly mounted in the manager container.
# It configures the necessary arguments, volumes, volume mounts, and container ports.
# Add the --webhook-cert-path argument for configuring the webhook certificate path
- op: add
path: /spec/template/spec/containers/0/args/-
value: --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs
# Add the volumeMount for the webhook certificates
- op: add
path: /spec/template/spec/containers/0/volumeMounts/-
value:
mountPath: /tmp/k8s-webhook-server/serving-certs
name: webhook-certs
readOnly: true
# Add the port configuration for the webhook server
- op: add
path: /spec/template/spec/containers/0/ports/-
value:
containerPort: 9443
name: webhook-server
protocol: TCP
# Add the volume configuration for the webhook certificates
- op: add
path: /spec/template/spec/volumes/-
value:
name: webhook-certs
secret:
secretName: webhook-server-cert

View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: controller-manager-metrics-service
namespace: system
spec:
ports:
- name: https
port: 8443
protocol: TCP
targetPort: 8443
selector:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator

View File

@ -1,8 +0,0 @@
# This patch add annotation to admission webhook config and
# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: mutating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)

View File

@ -1,14 +1,18 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- manager.yaml
generatorOptions:
disableNameSuffixHash: true
configMapGenerator:
- files:
- controller_manager_config.yaml
name: manager-config
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: controller
newName: controller
newTag: latest
newName: open-feature-operator-local
newTag: validate

View File

@ -3,6 +3,7 @@ kind: Namespace
metadata:
labels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
name: system
---
apiVersion: apps/v1
@ -12,10 +13,13 @@ metadata:
namespace: system
labels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
spec:
selector:
matchLabels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
replicas: 1
template:
metadata:
@ -23,6 +27,8 @@ spec:
kubectl.kubernetes.io/default-container: manager
labels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
spec:
securityContext:
runAsNonRoot: true
@ -36,11 +42,14 @@ spec:
fieldPath: metadata.namespace
args:
- --leader-elect
- --flagd-cpu-limit=0.5
- --flagd-ram-limit=64M
- --sidecar-cpu-limit=500m
- --sidecar-ram-limit=64Mi
- --sidecar-cpu-request=200m
- --sidecar-ram-request=32Mi
imagePullPolicy: IfNotPresent
image: controller:main
name: manager
ports: []
securityContext:
allowPrivilegeEscalation: false
runAsNonRoot: true
@ -65,5 +74,7 @@ spec:
requests:
cpu: 10m
memory: 64Mi
volumeMounts: []
volumes: []
serviceAccountName: controller-manager
terminationGracePeriodSeconds: 10

View File

@ -0,0 +1,27 @@
# This NetworkPolicy allows ingress traffic
# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those
# namespaces are able to gather data from the metrics endpoint.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: allow-metrics-traffic
namespace: system
spec:
podSelector:
matchLabels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
policyTypes:
- Ingress
ingress:
# This allows ingress traffic from any namespace with the label metrics: enabled
- from:
- namespaceSelector:
matchLabels:
metrics: enabled # Only from namespaces with this label
ports:
- port: 8443
protocol: TCP

View File

@ -0,0 +1,27 @@
# This NetworkPolicy allows ingress traffic to your webhook server running
# as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks
# will only work when applied in namespaces labeled with 'webhook: enabled'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: allow-webhook-traffic
namespace: system
spec:
podSelector:
matchLabels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
policyTypes:
- Ingress
ingress:
# This allows ingress traffic from any namespace with the label webhook: enabled
- from:
- namespaceSelector:
matchLabels:
webhook: enabled # Only from namespaces with this label
ports:
- port: 443
protocol: TCP

View File

@ -0,0 +1,2 @@
resources:
- allow-metrics-traffic.yaml

View File

@ -0,0 +1,21 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
spec:
dnsNames:
- SERVICE_NAME.{{ include "chart.namespace" . }}.svc
- SERVICE_NAME.{{ include "chart.namespace" . }}.svc.cluster.local
---
# The following manifests contain a self-signed issuer CR and a metrics certificate CR.
# More document can be found at https://docs.cert-manager.io
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: metrics-certs # this name should match the one appeared in kustomizeconfig.yaml
spec:
dnsNames:
# SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize
# replacements in the config/default/kustomization.yaml file.
- SERVICE_NAME.{{ include "chart.namespace" . }}.svc
- SERVICE_NAME.{{ include "chart.namespace" . }}.svc.cluster.local

View File

@ -3,6 +3,6 @@ kind: ControllerManagerConfig
health:
healthProbeBindAddress: "{{ .Values.managerConfig.controllerManagerConfigYaml.health.healthProbeBindAddress }}"
metrics:
bindAddress: "{{ .Values.managerConfig.controllerManagerConfigYaml.metrics.bindAddress }}"
bindAddress: "{{ .Values.managerConfig.controllerManagerConfigYaml.metrics.bindAddress }}:{{ .Values.managerConfig.controllerManagerConfigYaml.metrics.bindPort }}"
webhook:
port: 0{{ .Values.managerConfig.controllerManagerConfigYaml.webhook.port }}

View File

@ -0,0 +1,5 @@
$patch: delete
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: validating-webhook-configuration

View File

@ -0,0 +1,16 @@
# delete the default webhook-server port (to avoid duplicate) since we build it from helm
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
$patch: delete

View File

@ -1,5 +1,5 @@
# import the default deployment as the base
bases:
resources:
- ../../default
# replace the default namespace with {{ include "chart.namespace" . }}
@ -11,12 +11,55 @@ namespace: |-
# merge the exclude-ns.yaml with the existing namespace definition, this contains the `$patch: delete` directive allowing
# for the helm chart to define the namespace conditionally (only deploys when no namespace is provided and the default
# (open-feature-operator-system) is used
patchesStrategicMerge:
- exclude-ns.yaml
- manager.yaml
patches:
- path: exclude-ns.yaml
- path: manager.yaml
- path: exclude-webhook-server-container-port.yaml
- path: exclude-validatingwebhook.yaml
- path: mutatingwebhook.yaml
- path: certificate-patch.yaml
configMapGenerator:
- name: manager-config
behavior: merge
files:
- controller_manager_config.yaml
replacements:
- source: # Uncomment the following block to enable certificates for metrics
kind: Service
version: v1
name: controller-manager-metrics-service
fieldPath: metadata.name
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: metrics-certs
fieldPaths:
- spec.dnsNames.0
- spec.dnsNames.1
options:
delimiter: '.'
index: 0
create: true
- source: # Uncomment the following block if you have any webhook
kind: Service
version: v1
name: webhook-service
fieldPath: .metadata.name # Name of the service
targets:
- select:
kind: Certificate
group: cert-manager.io
version: v1
name: serving-cert
fieldPaths:
- spec.dnsNames.0
- spec.dnsNames.1
options:
delimiter: '.'
index: 0
create: true

View File

@ -6,7 +6,19 @@ metadata:
spec:
replicas: 0{{ .Values.controllerManager.replicas }}
template:
spec:
metadata:
# this is transformed by .github/scripts/strip-kustomize-helm.sh
annotations:
___delete_me___: "___ ___newline___{{ if .Values.annotations }}{{___space___toYaml___space___.Values.annotations___space___|___space___indent___space___8___space___}}{{ end }}___"
# this is transformed by .github/scripts/strip-kustomize-helm.sh
labels:
___delete_me___: "___ ___newline___{{ if .Values.labels }}___newline___{{___space___toYaml___space___.Values.labels___space___|___space___indent___space___8___space___}}{{ end }}___"
spec:
# this is transformed by .github/scripts/strip-kustomize-helm.sh
___imagePullSecrets___: "___ ___newline___ {{ toYaml .Values.imagePullSecrets___space___|___space___indent___space___8___space___}}___"
# this is transformed by .github/scripts/strip-kustomize-helm.sh
hostNetwork: "___{{ .Values.controllerManager.manager.hostNetwork }}___"
dnsPolicy: "{{ .Values.controllerManager.manager.dnsPolicy }}"
containers:
- name: manager
image: "{{ .Values.controllerManager.manager.image.repository }}:{{ .Values.controllerManager.manager.image.tag }}"
@ -17,45 +29,89 @@ spec:
requests:
cpu: "{{ .Values.controllerManager.manager.resources.requests.cpu }}"
memory: "{{ .Values.controllerManager.manager.resources.requests.memory }}"
env:
- name: SIDECAR_MANAGEMENT_PORT
value: "{{ .Values.sidecarConfiguration.managementPort }}"
- name: SIDECAR_PORT
value: "{{ .Values.sidecarConfiguration.port }}"
- name: SIDECAR_SOCKET_PATH
value: "{{ .Values.sidecarConfiguration.socketPath }}"
- name: SIDECAR_IMAGE
value: "{{ .Values.sidecarConfiguration.image.repository }}"
- name: SIDECAR_TAG
value: "{{ .Values.sidecarConfiguration.image.tag }}"
- name: SIDECAR_PROVIDER_ARGS
value: "{{ .Values.sidecarConfiguration.providerArgs }}"
- name: SIDECAR_ENV_VAR_PREFIX
value: "{{ .Values.sidecarConfiguration.envVarPrefix }}"
- name: SIDECAR_SYNC_PROVIDER
value: "{{ .Values.sidecarConfiguration.defaultSyncProvider }}"
- name: SIDECAR_EVALUATOR
value: "{{ .Values.sidecarConfiguration.evaluator }}"
- name: SIDECAR_LOG_FORMAT
value: "{{ .Values.sidecarConfiguration.logFormat }}"
- name: SIDECAR_PROBES_ENABLED
value: "{{ .Values.sidecarConfiguration.probesEnabled }}"
- name: FLAGD_PROXY_IMAGE
value: "{{ .Values.flagdProxyConfiguration.image.repository }}"
- name: FLAGD_PROXY_TAG
value: "{{ .Values.flagdProxyConfiguration.image.tag }}"
- name: FLAGD_PROXY_PORT
value: "{{ .Values.flagdProxyConfiguration.port }}"
- name: FLAGD_PROXY_MANAGEMENT_PORT
value: "{{ .Values.flagdProxyConfiguration.managementPort }}"
- name: FLAGD_PROXY_DEBUG_LOGGING
value: "{{ .Values.flagdProxyConfiguration.debugLogging }}"
- name: kube-rbac-proxy
image: "{{ .Values.controllerManager.kubeRbacProxy.image.repository }}:{{ .Values.controllerManager.kubeRbacProxy.image.tag }}"
resources:
limits:
cpu: "{{ .Values.controllerManager.kubeRbacProxy.resources.limits.cpu }}"
memory: "{{ .Values.controllerManager.kubeRbacProxy.resources.limits.memory }}"
requests:
cpu: "{{ .Values.controllerManager.kubeRbacProxy.resources.requests.cpu }}"
memory: "{{ .Values.controllerManager.kubeRbacProxy.resources.requests.memory }}"
ports:
- containerPort: "___ {{ .Values.managerConfig.controllerManagerConfigYaml.webhook.port }} ___"
name: webhook-server
protocol: TCP
- containerPort: "___ {{ .Values.managerConfig.controllerManagerConfigYaml.metrics.bindPort }} ___"
name: metrics-server
protocol: TCP
env:
- name: SIDECAR_MANAGEMENT_PORT
value: "{{ .Values.sidecarConfiguration.managementPort }}"
- name: SIDECAR_PORT
value: "{{ .Values.sidecarConfiguration.port }}"
- name: SIDECAR_SOCKET_PATH
value: "{{ .Values.sidecarConfiguration.socketPath }}"
- name: SIDECAR_IMAGE
value: "{{ .Values.sidecarConfiguration.image.repository }}"
- name: SIDECAR_TAG
value: "{{ .Values.sidecarConfiguration.image.tag }}"
- name: SIDECAR_PROVIDER_ARGS
value: "{{ .Values.sidecarConfiguration.providerArgs }}"
- name: SIDECAR_ENV_VAR_PREFIX
value: "{{ .Values.sidecarConfiguration.envVarPrefix }}"
- name: SIDECAR_SYNC_PROVIDER
value: "{{ .Values.sidecarConfiguration.defaultSyncProvider }}"
- name: SIDECAR_EVALUATOR
value: "{{ .Values.sidecarConfiguration.evaluator }}"
- name: SIDECAR_LOG_FORMAT
value: "{{ .Values.sidecarConfiguration.logFormat }}"
- name: SIDECAR_PROBES_ENABLED
value: "{{ .Values.sidecarConfiguration.probesEnabled }}"
- name: FLAGD_PROXY_IMAGE
value: "{{ .Values.flagdProxyConfiguration.image.repository }}"
- name: FLAGD_PROXY_REPLICA_COUNT
value: "{{ .Values.flagdProxyConfiguration.replicaCount }}"
- name: FLAGD_PROXY_TAG
value: "{{ .Values.flagdProxyConfiguration.image.tag }}"
- name: FLAGD_PROXY_PORT
value: "{{ .Values.flagdProxyConfiguration.port }}"
- name: FLAGD_PROXY_MANAGEMENT_PORT
value: "{{ .Values.flagdProxyConfiguration.managementPort }}"
- name: FLAGD_PROXY_DEBUG_LOGGING
value: "{{ .Values.flagdProxyConfiguration.debugLogging }}"
- name: FLAGD_IMAGE
value: "{{ .Values.flagdConfiguration.image.repository }}"
- name: FLAGD_TAG
value: "{{ .Values.flagdConfiguration.image.tag }}"
- name: FLAGD_PORT
value: "{{ .Values.flagdConfiguration.port }}"
- name: FLAGD_OFREP_PORT
value: "{{ .Values.flagdConfiguration.ofrepPort }}"
- name: FLAGD_SYNC_PORT
value: "{{ .Values.flagdConfiguration.syncPort }}"
- name: FLAGD_MANAGEMENT_PORT
value: "{{ .Values.flagdConfiguration.managementPort }}"
- name: FLAGD_DEBUG_LOGGING
value: "{{ .Values.flagdConfiguration.debugLogging }}"
- name: FLAGS_VALIDATION_ENABLED
value: "{{ .Values.managerConfig.flagsValidationEnabled }}"
- name: IN_PROCESS_PORT
value: "{{ .Values.inProcessConfiguration.port }}"
- name: IN_PROCESS_HOST
value: "{{ .Values.inProcessConfiguration.host }}"
- name: IN_PROCESS_SOCKET_PATH
value: "{{ .Values.inProcessConfiguration.socketPath }}"
- name: IN_PROCESS_TLS
value: "{{ .Values.inProcessConfiguration.tls }}"
- name: IN_PROCESS_OFFLINE_FLAG_SOURCE_PATH
value: "{{ .Values.inProcessConfiguration.offlineFlagSourcePath }}"
- name: IN_PROCESS_SELECTOR
value: "{{ .Values.inProcessConfiguration.selector }}"
- name: IN_PROCESS_CACHE
value: "{{ .Values.inProcessConfiguration.cache.type }}"
- name: IN_PROCESS_ENV_VAR_PREFIX
value: "{{ .Values.inProcessConfiguration.envVarPrefix }}"
- name: IN_PROCESS_CACHE_MAX_SIZE
value: "{{ .Values.inProcessConfiguration.cache.size }}"
args:
- --leader-elect
- --sidecar-cpu-limit={{ .Values.sidecarConfiguration.resources.limits.cpu }}
- --sidecar-ram-limit={{ .Values.sidecarConfiguration.resources.limits.memory }}
- --sidecar-cpu-request={{ .Values.sidecarConfiguration.resources.requests.cpu }}
- --sidecar-ram-request={{ .Values.sidecarConfiguration.resources.requests.memory }}
- --image-pull-secrets={{ range .Values.imagePullSecrets }}{{ .name }},{{- end }}
- --metrics-bind-address=:{{ .Values.managerConfig.controllerManagerConfigYaml.metrics.bindPort }}
- --labels={{ $labelKeys := keys .Values.labels -}}{{- $labelPairs := list -}}{{- range $key := $labelKeys -}}{{- $labelPairs = append $labelPairs (printf "%s:%s" $key (index $.Values.labels $key)) -}}{{- end -}}{{- join "," $labelPairs }}
- --annotations={{ $annotationKeys := keys .Values.annotations -}}{{- $annotationPairs := list -}}{{- range $key := $annotationKeys -}}{{- $annotationPairs = append $annotationPairs (printf "%s:%s" $key (index $.Values.annotations $key)) -}}{{- end -}}{{- join "," $annotationPairs }}

View File

@ -0,0 +1,10 @@
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: mutating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: "___'{{ include \"chart.namespace\" . }}/open-feature-operator-serving-cert'___"
webhooks:
- name: mutate.openfeature.dev
failurePolicy: "___{{ .Values.mutatingWebhook.failurePolicy }}___"
objectSelector: "___{{ toYaml .Values.mutatingWebhook.objectSelector | nindent 4 }}___"

View File

@ -1,2 +1,11 @@
resources:
- monitor.yaml
# [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus
# to securely reference certificates created and managed by cert-manager.
# Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml
# to mount the "metrics-server-cert" secret in the Manager Deployment.
patches:
- path: monitor_tls_patch.yaml
target:
kind: ServiceMonitor

View File

@ -1,20 +1,27 @@
# Prometheus Monitor Service (Metrics)
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: controller-manager-metrics-monitor
namespace: system
spec:
endpoints:
- path: /metrics
port: https
port: https # Ensure this is the name of the port that exposes HTTPS metrics
scheme: https
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
tlsConfig:
# TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables
# certificate verification, exposing the system to potential man-in-the-middle attacks.
# For production environments, it is recommended to use cert-manager for automatic TLS certificate management.
# To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml,
# which securely references the certificate from the 'metrics-server-cert' secret.
insecureSkipVerify: true
selector:
matchLabels:
control-plane: controller-manager
app.kubernetes.io/name: open-feature-operator

View File

@ -0,0 +1,22 @@
# Patch for Prometheus ServiceMonitor to enable secure TLS configuration
# using certificates managed by cert-manager
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: controller-manager-metrics-monitor
namespace: system
spec:
endpoints:
- tlsConfig:
insecureSkipVerify: false
ca:
secret:
name: metrics-server-cert
key: ca.crt
cert:
secret:
name: metrics-server-cert
key: tls.crt
keySecret:
name: metrics-server-cert
key: tls.key

View File

@ -0,0 +1,31 @@
# permissions for end users to edit flagds.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: flagd-editor-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: open-feature-operator
app.kubernetes.io/part-of: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: flagd-editor-role
rules:
- apiGroups:
- core.openfeature.dev
resources:
- flagds
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- core.openfeature.dev
resources:
- flagds/status
verbs:
- get

View File

@ -0,0 +1,27 @@
# permissions for end users to view flagds.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: flagd-viewer-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: open-feature-operator
app.kubernetes.io/part-of: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: flagd-viewer-role
rules:
- apiGroups:
- core.openfeature.dev
resources:
- flagds
verbs:
- get
- list
- watch
- apiGroups:
- core.openfeature.dev
resources:
- flagds/status
verbs:
- get

View File

@ -0,0 +1,31 @@
# permissions for end users to edit inprocessconfigurations.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/name: clusterrole
app.kubernetes.io/instance: inprocessconfiguration-editor-role
app.kubernetes.io/component: rbac
app.kubernetes.io/created-by: open-feature-operator
app.kubernetes.io/part-of: open-feature-operator
app.kubernetes.io/managed-by: kustomize
name: inprocessconfiguration-editor-role
rules:
- apiGroups:
- core.openfeature.dev
resources:
- inprocessconfigurations
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- core.openfeature.dev
resources:
- inprocessconfigurations/status
verbs:
- get

Some files were not shown because too many files have changed in this diff Show More