Compare commits

...

164 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
github-actions[bot] e39e7638a1
chore: release apis 0.2.40 (#620)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-04-22 11:13:20 -07:00
Martin Coetzee 18ac733191
feat: added interval to the openfeature api source (#619)
Signed-off-by: martin.coetzee <martin.coetzee@team.telstra.com>
Co-authored-by: martin.coetzee <martin.coetzee@team.telstra.com>
2024-04-22 09:47:18 -07:00
renovate[bot] b6daece6c4
chore(deps): update module golang.org/x/net to v0.24.0 (#613)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-17 11:30:50 -04:00
Michael Beemer 2e59477344
docs: bump cert manager version
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-02-29 15:09:25 -05:00
Michael Beemer de2f2b59b3
docs: bump cert manager version
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-02-29 15:08:17 -05:00
renovate[bot] 4eda2ca837
chore(deps): update actions/checkout action to v4 (#603)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-26 13:31:05 -05:00
renovate[bot] 8800728e14
chore(deps): update helm/kind-action action to v1.9.0 (#608)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-26 13:20:37 -05:00
github-actions[bot] 04c0a2ca71
chore: release 0.5.4 (#595)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-02-21 10:02:19 -05:00
github-actions[bot] c53a72b0d4
chore: release apis 0.2.39 (#590)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2024-02-21 09:32:42 -05:00
Kavindu Dodanduwa a1fc38a418
chore: regex to match all go files (#607)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2024-02-20 21:32:48 -05:00
renovate[bot] 0e03f47c29
chore(deps): update open-feature/flagd (#600)
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-02-20 21:22:59 -05:00
renovate[bot] e4476e2e5d
chore(deps): update actions/cache action to v4 (#602)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-20 14:13:51 -05:00
renovate[bot] 2b9d63a6db
chore(deps): update curlimages/curl docker tag to v8.6.0 (#599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-20 14:02:22 -05:00
odubajDT 73d6319820
chore: bump go to 1.21 (#604)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2024-02-14 07:01:02 +01:00
Michael Beemer ffc6cec3b1
docs: fix link to the flagd flag definition
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2024-01-29 14:37:20 -05:00
odubajDT 3271f33623
feat: auto-upgrade flagd-proxy with OFO upgrades (#596)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Signed-off-by: odubajDT <93584209+odubajDT@users.noreply.github.com>
Co-authored-by: Giovanni Liva <giovanni.liva@dynatrace.com>
2024-01-24 07:29:57 +01:00
Todd Baert f3f9427287
chore: add link to tutorial in README (#594)
Signed-off-by: Todd Baert <toddbaert@gmail.com>
2024-01-08 08:52:33 -05:00
github-actions[bot] 0affaa5968
chore: release 0.5.3 (#581)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2023-12-29 11:24:10 -05:00
Todd Baert a5dfbe1aa2
chore: add default timeout to make (#593)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2023-12-29 11:14:11 -05:00
Todd Baert f6a154d92a
chore: update readme tag version (#592)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2023-12-29 10:38:50 -05:00
Todd Baert 1444328691
fix: flagd mgmt port setting ignored (#588)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2023-12-20 11:09:21 +01:00
Erik Westra f79c46f36c
chore: Remove metrics-port flag/usage from flagdproxy startup (#587)
Signed-off-by: Erik Westra <e.s.westra.95@gmail.com>
2023-12-19 15:56:43 -05:00
Henry Chen 5a7b2c6be1
chore: update `FeatureFlagSource` documentation for v1beta1 (#584)
Signed-off-by: Henry Chen <1474479+chenhunghan@users.noreply.github.com>
2023-12-19 14:21:25 -05:00
odubajDT a6fa04f590
fix: create index for pod annotation path for allowkubernetessync annotation instead of deployment (#582)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-12-08 11:21:38 -05:00
renovate[bot] 70fb5d9549
chore(deps): update dependency bitnami-labs/readme-generator-for-helm to v2.6.0 (#525)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-06 20:41:17 -05:00
github-actions[bot] 370db50556
chore: release 0.5.2 (#572)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-06 13:14:33 -05:00
Michael Beemer 5d8c8299bc
fix: bump flagd and flagd proxy version (#577)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
2023-12-06 13:09:55 -05:00
renovate[bot] 5262fa7dc1
chore(deps): update docker/metadata-action digest to 31cebac (#520)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-06 10:24:00 -05:00
Kavindu Dodanduwa 361d068a46
chore: add helm migration section (#573)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-12-05 12:40:31 -05:00
Kavindu Dodanduwa 8bf9e42fbc
chore: migration docs (#571)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-12-04 16:52:38 -05:00
github-actions[bot] f239a25db2
chore: release 0.5.1 (#570)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-12-01 11:11:18 -05:00
Michael Beemer b9b619dcd5
fix: use webhook ns if empty, more test versions (#568)
Signed-off-by: Michael Beemer <beeme1mr@users.noreply.github.com>
Signed-off-by: Todd Baert <toddbaert@gmail.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2023-12-01 10:54:47 -05:00
github-actions[bot] 4c0fe34fee
chore: release 0.5.0 (#567)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 13:21:34 -08:00
Kavindu Dodanduwa c8c6101926
fix: fix build (#566)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-11-29 16:19:07 -05:00
github-actions[bot] e32a8724c9
chore: release 0.4.0 (#563)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 12:38:31 -08:00
Kavindu Dodanduwa 5ac4be3a24
chore: ignore component for release tag and make release dependable (#564)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-11-29 12:25:01 -08:00
Kavindu Dodanduwa e231787745
fix: Revert "feat: update api version to v0.2.38" (#562)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-11-29 14:34:57 -05:00
github-actions[bot] 002f2ddec7
chore: release operator 0.3.0 (#545)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 10:31:52 -08:00
Kavindu Dodanduwa d1f247727c
feat: update api version to v0.2.38 (#561)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-11-29 10:18:49 -08:00
github-actions[bot] 069e275421
chore: release apis 0.2.38 (#560)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 12:49:46 -05:00
Todd Baert f7c79e4c6f
chore: revert recent release (#559)
Signed-off-by: Todd Baert <todd.baert@dynatrace.com>
2023-11-29 12:46:19 -05:00
github-actions[bot] 4ecbc9b8ee
chore: release apis 0.2.38 (#558)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-29 09:39:40 -08:00
Kavindu Dodanduwa 318c52d2ba
chore: fix file source documentation (#556)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
2023-11-29 12:33:30 -05:00
Kavindu Dodanduwa ccb8c1d6e1
fix: Revert "chore: release apis 0.2.38" (#557)
Signed-off-by: Kavindu Dodanduwa <kavindudodanduwa@gmail.com>
2023-11-29 12:25:36 -05:00
github-actions[bot] c6165d426b
chore: release apis 0.2.38 (#548)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-28 08:46:02 -08:00
odubajDT 17a547f885
chore: refactor code to decrease complexity (#554)
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>
2023-11-22 08:14:44 +01:00
odubajDT ccc0471c15
docs: use v1beta1 API version (#553)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
Signed-off-by: odubajDT <93584209+odubajDT@users.noreply.github.com>
Co-authored-by: Meg McRoberts <meg.mcroberts@dynatrace.com>
Co-authored-by: Todd Baert <toddbaert@gmail.com>
Co-authored-by: Todd Baert <todd.baert@dynatrace.com>
2023-11-20 15:45:22 +01:00
odubajDT 233be79b56
feat: restricting sidecar image and tag setup (#550)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-20 07:04:43 +01:00
odubajDT 726a7f7149
chore: adapt API for sidecar image and tag restriction (#552)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-17 11:13:10 +01:00
odubajDT 61c77c0c13
chore: adapt shortcuts for custom resources (#551)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-17 10:08:17 +01:00
odubajDT 1287b0785f
chore: clean up unused API code after moving to v1beta1 (#543)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-17 06:56:44 +01:00
odubajDT d234410a80
feat!: use v1beta1 in operator logic (#539)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-16 15:19:45 +01:00
odubajDT e3c8b4290b
feat: prepare apis for v1beta1 controllers onboarding (#549)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-16 11:34:37 +01:00
odubajDT cdc4af495f
feat: introduce v1beta1/common package (#547)
Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
2023-11-16 09:34:11 +01:00
Giovanni Liva 18569182c1
chore: use apis tag instead of local replace (#546)
Signed-off-by: Giovanni Liva <giovanni.liva@dynatrace.com>
2023-11-15 09:46:06 -08:00
257 changed files with 24777 additions and 11525 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

@ -31,7 +31,7 @@ for namespace in $(kubectl get namespaces -o jsonpath='{.items[*].metadata.name}
createResourceReport "$logsDir/$namespace" "$namespace" "Daemonsets" false
createResourceReport "$logsDir/$namespace" "$namespace" "Statefulsets" false
createResourceReport "$logsDir/$namespace" "$namespace" "Jobs" false
createResourceReport "$logsDir/$namespace" "$namespace" "FeatureFlagConfiguration" false
createResourceReport "$logsDir/$namespace" "$namespace" "FlagSourceConfiguration" false
createResourceReport "$logsDir/$namespace" "$namespace" "FeatureFlag" false
createResourceReport "$logsDir/$namespace" "$namespace" "FeatureFlagSource" false
done

View File

@ -9,7 +9,7 @@
# Node >=16
# renovate: datasource=github-releases depName=bitnami-labs/readme-generator-for-helm
GENERATOR_VERSION="2.5.1"
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.20"
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.19
# 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: |
@ -34,40 +35,41 @@ jobs:
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
- name: Module cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: go-mod-cache
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/go.sum') }}
- name: Checkout repository
uses: actions/checkout@v3
- 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@v3
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.25.0, v1.26.0, v1.27.0 ]
steps:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: ${{ env.DEFAULT_GO_VERSION }}
- name: Checkout
uses: actions/checkout@v3
- 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@v3
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.8.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: always()
working-directory: ./.github/scripts
run: ./create-reports.sh
- name: Upload cluster logs
if: always()
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.19
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,27 +32,28 @@ 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 }}
release_tag_name: ${{ steps.release.outputs.tag_name }}
build-oci:
permissions:
packages: write # to push the container image
needs: release-please
runs-on: ubuntu-22.04
permissions:
packages: write # to push the container image
runs-on: ubuntu-24.04
if: ${{ needs.release-please.outputs.release_created }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
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@35e9aff4f5d665b5aa8a8f2adffaf8a1b5f49cc0
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: .
@ -106,22 +107,23 @@ jobs:
if: ${{ env.DRY_RUN != 'true' }}
release-assets:
needs: release-please
permissions:
contents: write # for softprops/action-gh-release to create GitHub release
needs: release-please
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
if: ${{ needs.release-please.outputs.release_created }}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
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,17 +146,17 @@ 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
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
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,14 +9,14 @@ 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@v3
uses: actions/checkout@v4
- name: Cache build tools
id: cache-build-tools
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ./bin
key: build-tools-${{ github.ref_name }}

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@v3
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

5
.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
@ -31,3 +32,7 @@ testbin/*
*.swo
*~
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.2.36",
"apis": "0.2.37"
".": "0.8.7",
"apis": "0.2.45"
}

View File

@ -1,5 +1,489 @@
# 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)
### ✨ New Features
* auto-upgrade flagd-proxy with OFO upgrades ([#596](https://github.com/open-feature/open-feature-operator/issues/596)) ([3271f33](https://github.com/open-feature/open-feature-operator/commit/3271f33623518408b0055b808c22434a46462a05))
### 🧹 Chore
* add link to tutorial in README ([#594](https://github.com/open-feature/open-feature-operator/issues/594)) ([f3f9427](https://github.com/open-feature/open-feature-operator/commit/f3f9427287199e28d3e11313bad616f0e781048b))
* bump go to 1.21 ([#604](https://github.com/open-feature/open-feature-operator/issues/604)) ([73d6319](https://github.com/open-feature/open-feature-operator/commit/73d6319820220fc114cdfc7d72f8c2327a35ec37))
* **deps:** update actions/cache action to v4 ([#602](https://github.com/open-feature/open-feature-operator/issues/602)) ([e4476e2](https://github.com/open-feature/open-feature-operator/commit/e4476e2e5d2e2178ef280e6da324590115b80cb6))
* **deps:** update curlimages/curl docker tag to v8.6.0 ([#599](https://github.com/open-feature/open-feature-operator/issues/599)) ([2b9d63a](https://github.com/open-feature/open-feature-operator/commit/2b9d63a6dbde5a716dc2e472e65b55ba36085c40))
* **deps:** update open-feature/flagd ([#600](https://github.com/open-feature/open-feature-operator/issues/600)) ([0e03f47](https://github.com/open-feature/open-feature-operator/commit/0e03f47c295592fd9eb94185b1a8d69c5fe52559))
* regex to match all go files ([#607](https://github.com/open-feature/open-feature-operator/issues/607)) ([a1fc38a](https://github.com/open-feature/open-feature-operator/commit/a1fc38a4186f297712ee077780a1c372026e58fb))
* release apis 0.2.39 ([#590](https://github.com/open-feature/open-feature-operator/issues/590)) ([c53a72b](https://github.com/open-feature/open-feature-operator/commit/c53a72b0d4f0ecbb6f839ae1af54621f4c152f42))
### 📚 Documentation
* fix link to the flagd flag definition ([ffc6cec](https://github.com/open-feature/open-feature-operator/commit/ffc6cec3b19d6d59f103c8d6083836bafa14c352))
## [0.5.3](https://github.com/open-feature/open-feature-operator/compare/v0.5.2...v0.5.3) (2023-12-29)
### 🐛 Bug Fixes
* create index for pod annotation path for allowkubernetessync annotation instead of deployment ([#582](https://github.com/open-feature/open-feature-operator/issues/582)) ([a6fa04f](https://github.com/open-feature/open-feature-operator/commit/a6fa04f590ad4ad6779ce85f4fc167b59f1b17a7))
* flagd mgmt port setting ignored ([#588](https://github.com/open-feature/open-feature-operator/issues/588)) ([1444328](https://github.com/open-feature/open-feature-operator/commit/1444328691450ee3967d862eebf3a293b4f9fe7c))
### 🧹 Chore
* add default timeout to make ([#593](https://github.com/open-feature/open-feature-operator/issues/593)) ([a5dfbe1](https://github.com/open-feature/open-feature-operator/commit/a5dfbe1aa24e17bd21fe4c5073e0cd40f11b6203))
* **deps:** update dependency bitnami-labs/readme-generator-for-helm to v2.6.0 ([#525](https://github.com/open-feature/open-feature-operator/issues/525)) ([70fb5d9](https://github.com/open-feature/open-feature-operator/commit/70fb5d95497346dac9f83058105de4d828d75c96))
* Remove metrics-port flag/usage from flagdproxy startup ([#587](https://github.com/open-feature/open-feature-operator/issues/587)) ([f79c46f](https://github.com/open-feature/open-feature-operator/commit/f79c46f36cfda1134c523e962925cfdfd0d2b0b3))
* update `FeatureFlagSource` documentation for v1beta1 ([#584](https://github.com/open-feature/open-feature-operator/issues/584)) ([5a7b2c6](https://github.com/open-feature/open-feature-operator/commit/5a7b2c6be1d38fe344c98f0e7d816852e9eb744f))
* update readme tag version ([#592](https://github.com/open-feature/open-feature-operator/issues/592)) ([f6a154d](https://github.com/open-feature/open-feature-operator/commit/f6a154d92a6ed0633761523b5cb43606604a48a1))
## [0.5.2](https://github.com/open-feature/open-feature-operator/compare/v0.5.1...v0.5.2) (2023-12-06)
### 🐛 Bug Fixes
* bump flagd and flagd proxy version ([#577](https://github.com/open-feature/open-feature-operator/issues/577)) ([5d8c829](https://github.com/open-feature/open-feature-operator/commit/5d8c8299bc3030a2b14baaa6a0fb5b4f6f0d47ea))
### 🧹 Chore
* add helm migration section ([#573](https://github.com/open-feature/open-feature-operator/issues/573)) ([361d068](https://github.com/open-feature/open-feature-operator/commit/361d068a46d8d6ca5c96aa0889cdbe1ac53d538b))
* **deps:** update docker/metadata-action digest to 31cebac ([#520](https://github.com/open-feature/open-feature-operator/issues/520)) ([5262fa7](https://github.com/open-feature/open-feature-operator/commit/5262fa7dc15458330cdc13c277a7b0a115199326))
* migration docs ([#571](https://github.com/open-feature/open-feature-operator/issues/571)) ([8bf9e42](https://github.com/open-feature/open-feature-operator/commit/8bf9e42fbc8300d614b398e0b91146082a66abba))
## [0.5.1](https://github.com/open-feature/open-feature-operator/compare/v0.5.0...v0.5.1) (2023-12-01)
### 🐛 Bug Fixes
* use webhook ns if empty, more test versions ([#568](https://github.com/open-feature/open-feature-operator/issues/568)) ([b9b619d](https://github.com/open-feature/open-feature-operator/commit/b9b619dcd5133a48ca1248eba14419a30922e961))
## [0.5.0](https://github.com/open-feature/open-feature-operator/compare/v0.4.0...v0.5.0) (2023-11-29)
### ⚠ BREAKING CHANGES
* use v1beta1 in operator logic ([#539](https://github.com/open-feature/open-feature-operator/issues/539))
### ✨ New Features
* Introduce v1beta1 API version ([#535](https://github.com/open-feature/open-feature-operator/issues/535)) ([3acd492](https://github.com/open-feature/open-feature-operator/commit/3acd49289a40e8f07fd20aad46185ac42ceb1b7a))
* prepare apis for v1beta1 controllers onboarding ([#549](https://github.com/open-feature/open-feature-operator/issues/549)) ([e3c8b42](https://github.com/open-feature/open-feature-operator/commit/e3c8b4290be99d78b88ffef686531a38b97e61be))
* release APIs and Operator independently ([#541](https://github.com/open-feature/open-feature-operator/issues/541)) ([7b1af42](https://github.com/open-feature/open-feature-operator/commit/7b1af42ac41e63ccbb1820b31f579ffea679cff6))
* restricting sidecar image and tag setup ([#550](https://github.com/open-feature/open-feature-operator/issues/550)) ([233be79](https://github.com/open-feature/open-feature-operator/commit/233be79b56ccca32a1cb041bce53a9848f032a60))
* update api version to v0.2.38 ([#561](https://github.com/open-feature/open-feature-operator/issues/561)) ([d1f2477](https://github.com/open-feature/open-feature-operator/commit/d1f247727c5b6f4cb5154e94f1090aee0a442346))
* use v1beta1 in operator logic ([#539](https://github.com/open-feature/open-feature-operator/issues/539)) ([d234410](https://github.com/open-feature/open-feature-operator/commit/d234410a809760ba1c8592f95be56891e0cae855))
### 🐛 Bug Fixes
* fix build ([#566](https://github.com/open-feature/open-feature-operator/issues/566)) ([c8c6101](https://github.com/open-feature/open-feature-operator/commit/c8c61019266dc3fc379759bc22a9360279ee194a))
* Revert "chore: release apis 0.2.38" ([#557](https://github.com/open-feature/open-feature-operator/issues/557)) ([ccb8c1d](https://github.com/open-feature/open-feature-operator/commit/ccb8c1d6e12aa36e33239fd96bebbc57fc4ea3bc))
* Revert "feat: update api version to v0.2.38" ([#562](https://github.com/open-feature/open-feature-operator/issues/562)) ([e231787](https://github.com/open-feature/open-feature-operator/commit/e2317877451163b70d0fe8fb073937d3c7586b31))
### 🧹 Chore
* clean up unused API code after moving to v1beta1 ([#543](https://github.com/open-feature/open-feature-operator/issues/543)) ([1287b07](https://github.com/open-feature/open-feature-operator/commit/1287b0785fd99cb8bfeaf9fe112aa8a0ed6f5cf9))
* **deps:** update actions/setup-node action to v3.8.1 ([#522](https://github.com/open-feature/open-feature-operator/issues/522)) ([32ddf00](https://github.com/open-feature/open-feature-operator/commit/32ddf002e6c20732d990283946ec124304827bd3))
* fix file source documentation ([#556](https://github.com/open-feature/open-feature-operator/issues/556)) ([318c52d](https://github.com/open-feature/open-feature-operator/commit/318c52d2ba38dbfee6deb3f06d3392dc14d80a6c))
* ignore component for release tag and make release dependable ([#564](https://github.com/open-feature/open-feature-operator/issues/564)) ([5ac4be3](https://github.com/open-feature/open-feature-operator/commit/5ac4be3a24f73f1b66346840a3084f1ff5030627))
* refactor code to decrease complexity ([#554](https://github.com/open-feature/open-feature-operator/issues/554)) ([17a547f](https://github.com/open-feature/open-feature-operator/commit/17a547f88595cb6c177ca93e1a8b4ad49f3c1a5f))
* release 0.4.0 ([#563](https://github.com/open-feature/open-feature-operator/issues/563)) ([e32a872](https://github.com/open-feature/open-feature-operator/commit/e32a8724c9a0bbcb5226b16cd36d065ee358cd2d))
* release apis 0.2.37 ([#544](https://github.com/open-feature/open-feature-operator/issues/544)) ([854e72d](https://github.com/open-feature/open-feature-operator/commit/854e72d964fce51082220a60fc8a7319676e49c3))
* release apis 0.2.38 ([#548](https://github.com/open-feature/open-feature-operator/issues/548)) ([c6165d4](https://github.com/open-feature/open-feature-operator/commit/c6165d426b5be2af89e03695d24fe0b802fb1fe2))
* release apis 0.2.38 ([#558](https://github.com/open-feature/open-feature-operator/issues/558)) ([4ecbc9b](https://github.com/open-feature/open-feature-operator/commit/4ecbc9b8eeac4e1e86c0f4e11ffedf3dbc376f9a))
* release apis 0.2.38 ([#560](https://github.com/open-feature/open-feature-operator/issues/560)) ([069e275](https://github.com/open-feature/open-feature-operator/commit/069e2754210d1a71bc5b70c0d4e6e193f62a7bcb))
* release operator 0.3.0 ([#545](https://github.com/open-feature/open-feature-operator/issues/545)) ([002f2dd](https://github.com/open-feature/open-feature-operator/commit/002f2ddec77a2caf919280fb9bfe74ab092c27a5))
* revert recent release ([#559](https://github.com/open-feature/open-feature-operator/issues/559)) ([f7c79e4](https://github.com/open-feature/open-feature-operator/commit/f7c79e4c6f5a5dee05d7db1796bfb9891dbd53a0))
* use apis tag instead of local replace ([#546](https://github.com/open-feature/open-feature-operator/issues/546)) ([1856918](https://github.com/open-feature/open-feature-operator/commit/18569182c1f2eca3e29e9428a64239ac16ea3c08))
* use github-action for golangci-lint workflow ([#538](https://github.com/open-feature/open-feature-operator/issues/538)) ([a97d336](https://github.com/open-feature/open-feature-operator/commit/a97d336468d5a9b50662f4979784c8388ec10ec1))
### 📚 Documentation
* use v1beta1 API version ([#553](https://github.com/open-feature/open-feature-operator/issues/553)) ([ccc0471](https://github.com/open-feature/open-feature-operator/commit/ccc0471c15cb42a338cd4c1a69b0b1f7c7828837))
## [0.4.0](https://github.com/open-feature/open-feature-operator/compare/v0.3.0...v0.4.0) (2023-11-29)
### ⚠ BREAKING CHANGES
* use v1beta1 in operator logic ([#539](https://github.com/open-feature/open-feature-operator/issues/539))
### ✨ New Features
* Introduce v1beta1 API version ([#535](https://github.com/open-feature/open-feature-operator/issues/535)) ([3acd492](https://github.com/open-feature/open-feature-operator/commit/3acd49289a40e8f07fd20aad46185ac42ceb1b7a))
* prepare apis for v1beta1 controllers onboarding ([#549](https://github.com/open-feature/open-feature-operator/issues/549)) ([e3c8b42](https://github.com/open-feature/open-feature-operator/commit/e3c8b4290be99d78b88ffef686531a38b97e61be))
* release APIs and Operator independently ([#541](https://github.com/open-feature/open-feature-operator/issues/541)) ([7b1af42](https://github.com/open-feature/open-feature-operator/commit/7b1af42ac41e63ccbb1820b31f579ffea679cff6))
* restricting sidecar image and tag setup ([#550](https://github.com/open-feature/open-feature-operator/issues/550)) ([233be79](https://github.com/open-feature/open-feature-operator/commit/233be79b56ccca32a1cb041bce53a9848f032a60))
* update api version to v0.2.38 ([#561](https://github.com/open-feature/open-feature-operator/issues/561)) ([d1f2477](https://github.com/open-feature/open-feature-operator/commit/d1f247727c5b6f4cb5154e94f1090aee0a442346))
* use v1beta1 in operator logic ([#539](https://github.com/open-feature/open-feature-operator/issues/539)) ([d234410](https://github.com/open-feature/open-feature-operator/commit/d234410a809760ba1c8592f95be56891e0cae855))
### 🐛 Bug Fixes
* Revert "chore: release apis 0.2.38" ([#557](https://github.com/open-feature/open-feature-operator/issues/557)) ([ccb8c1d](https://github.com/open-feature/open-feature-operator/commit/ccb8c1d6e12aa36e33239fd96bebbc57fc4ea3bc))
* Revert "feat: update api version to v0.2.38" ([#562](https://github.com/open-feature/open-feature-operator/issues/562)) ([e231787](https://github.com/open-feature/open-feature-operator/commit/e2317877451163b70d0fe8fb073937d3c7586b31))
### 🧹 Chore
* clean up unused API code after moving to v1beta1 ([#543](https://github.com/open-feature/open-feature-operator/issues/543)) ([1287b07](https://github.com/open-feature/open-feature-operator/commit/1287b0785fd99cb8bfeaf9fe112aa8a0ed6f5cf9))
* **deps:** update actions/setup-node action to v3.8.1 ([#522](https://github.com/open-feature/open-feature-operator/issues/522)) ([32ddf00](https://github.com/open-feature/open-feature-operator/commit/32ddf002e6c20732d990283946ec124304827bd3))
* fix file source documentation ([#556](https://github.com/open-feature/open-feature-operator/issues/556)) ([318c52d](https://github.com/open-feature/open-feature-operator/commit/318c52d2ba38dbfee6deb3f06d3392dc14d80a6c))
* ignore component for release tag and make release dependable ([#564](https://github.com/open-feature/open-feature-operator/issues/564)) ([5ac4be3](https://github.com/open-feature/open-feature-operator/commit/5ac4be3a24f73f1b66346840a3084f1ff5030627))
* refactor code to decrease complexity ([#554](https://github.com/open-feature/open-feature-operator/issues/554)) ([17a547f](https://github.com/open-feature/open-feature-operator/commit/17a547f88595cb6c177ca93e1a8b4ad49f3c1a5f))
* release apis 0.2.37 ([#544](https://github.com/open-feature/open-feature-operator/issues/544)) ([854e72d](https://github.com/open-feature/open-feature-operator/commit/854e72d964fce51082220a60fc8a7319676e49c3))
* release apis 0.2.38 ([#548](https://github.com/open-feature/open-feature-operator/issues/548)) ([c6165d4](https://github.com/open-feature/open-feature-operator/commit/c6165d426b5be2af89e03695d24fe0b802fb1fe2))
* release apis 0.2.38 ([#558](https://github.com/open-feature/open-feature-operator/issues/558)) ([4ecbc9b](https://github.com/open-feature/open-feature-operator/commit/4ecbc9b8eeac4e1e86c0f4e11ffedf3dbc376f9a))
* release apis 0.2.38 ([#560](https://github.com/open-feature/open-feature-operator/issues/560)) ([069e275](https://github.com/open-feature/open-feature-operator/commit/069e2754210d1a71bc5b70c0d4e6e193f62a7bcb))
* release operator 0.3.0 ([#545](https://github.com/open-feature/open-feature-operator/issues/545)) ([002f2dd](https://github.com/open-feature/open-feature-operator/commit/002f2ddec77a2caf919280fb9bfe74ab092c27a5))
* revert recent release ([#559](https://github.com/open-feature/open-feature-operator/issues/559)) ([f7c79e4](https://github.com/open-feature/open-feature-operator/commit/f7c79e4c6f5a5dee05d7db1796bfb9891dbd53a0))
* use apis tag instead of local replace ([#546](https://github.com/open-feature/open-feature-operator/issues/546)) ([1856918](https://github.com/open-feature/open-feature-operator/commit/18569182c1f2eca3e29e9428a64239ac16ea3c08))
* use github-action for golangci-lint workflow ([#538](https://github.com/open-feature/open-feature-operator/issues/538)) ([a97d336](https://github.com/open-feature/open-feature-operator/commit/a97d336468d5a9b50662f4979784c8388ec10ec1))
### 📚 Documentation
* use v1beta1 API version ([#553](https://github.com/open-feature/open-feature-operator/issues/553)) ([ccc0471](https://github.com/open-feature/open-feature-operator/commit/ccc0471c15cb42a338cd4c1a69b0b1f7c7828837))
## [0.3.0](https://github.com/open-feature/open-feature-operator/compare/operator-v0.2.36...operator/v0.3.0) (2023-11-29)
### ⚠ BREAKING CHANGES
* use v1beta1 in operator logic ([#539](https://github.com/open-feature/open-feature-operator/issues/539))
### ✨ New Features
* Introduce v1beta1 API version ([#535](https://github.com/open-feature/open-feature-operator/issues/535)) ([3acd492](https://github.com/open-feature/open-feature-operator/commit/3acd49289a40e8f07fd20aad46185ac42ceb1b7a))
* prepare apis for v1beta1 controllers onboarding ([#549](https://github.com/open-feature/open-feature-operator/issues/549)) ([e3c8b42](https://github.com/open-feature/open-feature-operator/commit/e3c8b4290be99d78b88ffef686531a38b97e61be))
* release APIs and Operator independently ([#541](https://github.com/open-feature/open-feature-operator/issues/541)) ([7b1af42](https://github.com/open-feature/open-feature-operator/commit/7b1af42ac41e63ccbb1820b31f579ffea679cff6))
* restricting sidecar image and tag setup ([#550](https://github.com/open-feature/open-feature-operator/issues/550)) ([233be79](https://github.com/open-feature/open-feature-operator/commit/233be79b56ccca32a1cb041bce53a9848f032a60))
* update api version to v0.2.38 ([#561](https://github.com/open-feature/open-feature-operator/issues/561)) ([d1f2477](https://github.com/open-feature/open-feature-operator/commit/d1f247727c5b6f4cb5154e94f1090aee0a442346))
* use v1beta1 in operator logic ([#539](https://github.com/open-feature/open-feature-operator/issues/539)) ([d234410](https://github.com/open-feature/open-feature-operator/commit/d234410a809760ba1c8592f95be56891e0cae855))
### 🐛 Bug Fixes
* Revert "chore: release apis 0.2.38" ([#557](https://github.com/open-feature/open-feature-operator/issues/557)) ([ccb8c1d](https://github.com/open-feature/open-feature-operator/commit/ccb8c1d6e12aa36e33239fd96bebbc57fc4ea3bc))
### 🧹 Chore
* clean up unused API code after moving to v1beta1 ([#543](https://github.com/open-feature/open-feature-operator/issues/543)) ([1287b07](https://github.com/open-feature/open-feature-operator/commit/1287b0785fd99cb8bfeaf9fe112aa8a0ed6f5cf9))
* **deps:** update actions/setup-node action to v3.8.1 ([#522](https://github.com/open-feature/open-feature-operator/issues/522)) ([32ddf00](https://github.com/open-feature/open-feature-operator/commit/32ddf002e6c20732d990283946ec124304827bd3))
* fix file source documentation ([#556](https://github.com/open-feature/open-feature-operator/issues/556)) ([318c52d](https://github.com/open-feature/open-feature-operator/commit/318c52d2ba38dbfee6deb3f06d3392dc14d80a6c))
* refactor code to decrease complexity ([#554](https://github.com/open-feature/open-feature-operator/issues/554)) ([17a547f](https://github.com/open-feature/open-feature-operator/commit/17a547f88595cb6c177ca93e1a8b4ad49f3c1a5f))
* release apis 0.2.37 ([#544](https://github.com/open-feature/open-feature-operator/issues/544)) ([854e72d](https://github.com/open-feature/open-feature-operator/commit/854e72d964fce51082220a60fc8a7319676e49c3))
* release apis 0.2.38 ([#548](https://github.com/open-feature/open-feature-operator/issues/548)) ([c6165d4](https://github.com/open-feature/open-feature-operator/commit/c6165d426b5be2af89e03695d24fe0b802fb1fe2))
* release apis 0.2.38 ([#558](https://github.com/open-feature/open-feature-operator/issues/558)) ([4ecbc9b](https://github.com/open-feature/open-feature-operator/commit/4ecbc9b8eeac4e1e86c0f4e11ffedf3dbc376f9a))
* release apis 0.2.38 ([#560](https://github.com/open-feature/open-feature-operator/issues/560)) ([069e275](https://github.com/open-feature/open-feature-operator/commit/069e2754210d1a71bc5b70c0d4e6e193f62a7bcb))
* revert recent release ([#559](https://github.com/open-feature/open-feature-operator/issues/559)) ([f7c79e4](https://github.com/open-feature/open-feature-operator/commit/f7c79e4c6f5a5dee05d7db1796bfb9891dbd53a0))
* use apis tag instead of local replace ([#546](https://github.com/open-feature/open-feature-operator/issues/546)) ([1856918](https://github.com/open-feature/open-feature-operator/commit/18569182c1f2eca3e29e9428a64239ac16ea3c08))
* use github-action for golangci-lint workflow ([#538](https://github.com/open-feature/open-feature-operator/issues/538)) ([a97d336](https://github.com/open-feature/open-feature-operator/commit/a97d336468d5a9b50662f4979784c8388ec10ec1))
### 📚 Documentation
* use v1beta1 API version ([#553](https://github.com/open-feature/open-feature-operator/issues/553)) ([ccc0471](https://github.com/open-feature/open-feature-operator/commit/ccc0471c15cb42a338cd4c1a69b0b1f7c7828837))
## [0.2.36](https://github.com/open-feature/open-feature-operator/compare/v0.2.35...v0.2.36) (2023-08-07)

View File

@ -7,7 +7,7 @@ There are a few things to consider before contributing to open-feature-operator.
Firstly, there's [a code of conduct](https://github.com/open-feature/.github/blob/main/CODE_OF_CONDUCT.md).
TLDR: be respectful.
Any contributions are expected to include tests. These can be validated with `make test` or the automated github workflow will run them on PR creation.
Any contributions are expected to include tests. These can be validated with `make unit-test` or the automated github workflow will run them on PR creation.
The go version in the `go.mod` is the currently supported version of go.
@ -15,8 +15,8 @@ Thanks! Issues and pull requests following these guidelines are welcome.
## Development
### FeatureFlagConfiguration custom resource definition versioning
Custom resource definitions support multiple versions. The kubebuilder framework exposes a system to seamlessly convert between versions (using a "hub and spoke" model) maintaining backwards compatibility. It does this by injecting conversion webhooks that call our defined convert functions. The hub version of the `FeatureFlagConfiguration` custom resource definition (the version to which all other versions are converted) is `v1alpha1`.
### FeatureFlag custom resource definition versioning
Custom resource definitions support multiple versions. The kubebuilder framework exposes a system to seamlessly convert between versions (using a "hub and spoke" model) maintaining backwards compatibility. It does this by injecting conversion webhooks that call our defined convert functions. The hub version of the `FeatureFlag` custom resource definition (the version to which all other versions are converted) is `v1beta1`.
Follow [this tutorial](https://book.kubebuilder.io/multiversion-tutorial/conversion-concepts.html) to implement a new version of the custom resource definition.
### Local build
@ -29,12 +29,16 @@ make build-deploy-operator TAG=myTag RELEASE_REGISTRY=docker.io/user1 RELEASE_NA
Which will result in building the operator image `docker.io/user1/myImgName:myTag`, uploading it to your image registry
and deploying to your cluster. Please be aware that it is using the cluster your current kube-context is pointing to.
**Note:** All bash variables are optional, the default values are set and will result in an image `ghcr.io/openfeature/operator:latest`
> [!NOTE]
> All bash variables are optional, the default values are set and will result in an image `ghcr.io/openfeature/operator:latest`
### Autogenerated Documentation
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 pkg/ pkg/
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,9 +6,12 @@ ARCH?=amd64
IMG?=$(RELEASE_REGISTRY)/$(RELEASE_IMAGE)
# customize overlay to be used in the build, DEFAULT or HELM
KUSTOMIZE_OVERLAY ?= DEFAULT
CHART_VERSION=v0.2.36# 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))
@ -62,17 +65,26 @@ vet: ## Run go vet against code.
go vet ./...
.PHONY: unit-test
unit-test: manifests fmt vet generate envtest ## Run tests.
go test ./... -v -short -coverprofile cover.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"
echo "mode: set" > cover.out
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:
@ -80,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
@ -100,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.
@ -151,7 +163,7 @@ release-manifests: manifests kustomize
fi
.PHONY: deploy
deploy: generate manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
deploy: generate kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG)
$(KUSTOMIZE) build config/default | kubectl apply -f -
@ -162,10 +174,10 @@ 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 wait --for=condition=Available=True deploy --all -n 'cert-manager'
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'
kubectl wait --for=condition=Available=True deploy --all -n 'open-feature-operator-system' --timeout=$(WAIT_TIMEOUT_SECONDS)s
.PHONY: build-deploy-operator
build-deploy-operator:
@ -175,7 +187,7 @@ build-deploy-operator:
deploy-demo:
kubectl apply -f https://raw.githubusercontent.com/open-feature/playground/main/config/k8s/end-to-end.yaml
kubectl wait -l app=open-feature-demo --for=condition=Available=True deploy
kubectl wait -l app=open-feature-demo --for=condition=Available=True deploy --timeout=$(WAIT_TIMEOUT_SECONDS)s
kubectl port-forward service/open-feature-demo-service 30000:30000
delete-demo-deployment:
@ -197,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.
@ -238,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
@ -246,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

@ -12,9 +12,18 @@
## Get started
The OpenFeature Operator allows you to expose feature flags to your applications. It injects a [flagD](https://github.com/open-feature/flagd) sidecar into relevant pods exposes gRPC and HTTP interfaces for flag evaluation. To get started, follow the installation instructions in the [docs](./docs).
The OpenFeature Operator allows you to expose feature flags to your applications.
It injects a [flagd](https://github.com/open-feature/flagd) sidecar into relevant pods and exposes gRPC and HTTP interfaces for flag evaluation.
To get started, follow the installation instructions in the [docs](./docs).
<h2 align="center"><a href="https://killercoda.com/open-feature/scenario/openfeature-operator-demo" target="_blank">Try the OpenFeature Operator in the Killercoda Playground (in browser)</a></h2>
> [!NOTE]
> With version [v0.5.0](https://github.com/open-feature/open-feature-operator/releases/tag/v0.5.0), we have migrated
> to API version `v1beta1`. Please check the [migration guide](./docs/v1beta_migration.md) to migrate from old configurations.
## Demos
- [Try the OpenFeature Operator locally on your machine](https://openfeature.dev/docs/tutorials/ofo)
- [Try the OpenFeature Operator in the Killercoda Playground (in browser)](https://killercoda.com/open-feature/scenario/openfeature-operator-demo)
## Changelog
@ -24,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.

125
api/CHANGELOG.md Normal file
View File

@ -0,0 +1,125 @@
# 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)
### ✨ New Features
* added interval to the openfeature api source ([#619](https://github.com/open-feature/open-feature-operator/issues/619)) ([18ac733](https://github.com/open-feature/open-feature-operator/commit/18ac7331916f5fa19b2f0c8d2fe34f7ba9f1e595))
## [0.2.39](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.38...apis/v0.2.39) (2024-02-21)
### 🐛 Bug Fixes
* flagd mgmt port setting ignored ([#588](https://github.com/open-feature/open-feature-operator/issues/588)) ([1444328](https://github.com/open-feature/open-feature-operator/commit/1444328691450ee3967d862eebf3a293b4f9fe7c))
### 🧹 Chore
* bump go to 1.21 ([#604](https://github.com/open-feature/open-feature-operator/issues/604)) ([73d6319](https://github.com/open-feature/open-feature-operator/commit/73d6319820220fc114cdfc7d72f8c2327a35ec37))
## [0.2.38](https://github.com/open-feature/open-feature-operator/compare/apis/v0.2.37...apis/v0.2.38) (2023-11-29)
### ✨ New Features
* introduce v1beta1/common package ([#547](https://github.com/open-feature/open-feature-operator/issues/547)) ([cdc4af4](https://github.com/open-feature/open-feature-operator/commit/cdc4af495f370da7165fd67ad9ef54ccf74be3bf))
* prepare apis for v1beta1 controllers onboarding ([#549](https://github.com/open-feature/open-feature-operator/issues/549)) ([e3c8b42](https://github.com/open-feature/open-feature-operator/commit/e3c8b4290be99d78b88ffef686531a38b97e61be))
### 🐛 Bug Fixes
* Revert "chore: release apis 0.2.38" ([#557](https://github.com/open-feature/open-feature-operator/issues/557)) ([ccb8c1d](https://github.com/open-feature/open-feature-operator/commit/ccb8c1d6e12aa36e33239fd96bebbc57fc4ea3bc))
### 🧹 Chore
* adapt API for sidecar image and tag restriction ([#552](https://github.com/open-feature/open-feature-operator/issues/552)) ([726a7f7](https://github.com/open-feature/open-feature-operator/commit/726a7f7149067d2e2696f746a236151fbb67808c))
* adapt shortcuts for custom resources ([#551](https://github.com/open-feature/open-feature-operator/issues/551)) ([61c77c0](https://github.com/open-feature/open-feature-operator/commit/61c77c0c137ec624892c9738ee45828a137f6823))
* clean up unused API code after moving to v1beta1 ([#543](https://github.com/open-feature/open-feature-operator/issues/543)) ([1287b07](https://github.com/open-feature/open-feature-operator/commit/1287b0785fd99cb8bfeaf9fe112aa8a0ed6f5cf9))
* fix file source documentation ([#556](https://github.com/open-feature/open-feature-operator/issues/556)) ([318c52d](https://github.com/open-feature/open-feature-operator/commit/318c52d2ba38dbfee6deb3f06d3392dc14d80a6c))
* refactor code to decrease complexity ([#554](https://github.com/open-feature/open-feature-operator/issues/554)) ([17a547f](https://github.com/open-feature/open-feature-operator/commit/17a547f88595cb6c177ca93e1a8b4ad49f3c1a5f))
* release apis 0.2.38 ([#548](https://github.com/open-feature/open-feature-operator/issues/548)) ([c6165d4](https://github.com/open-feature/open-feature-operator/commit/c6165d426b5be2af89e03695d24fe0b802fb1fe2))
* release apis 0.2.38 ([#558](https://github.com/open-feature/open-feature-operator/issues/558)) ([4ecbc9b](https://github.com/open-feature/open-feature-operator/commit/4ecbc9b8eeac4e1e86c0f4e11ffedf3dbc376f9a))
* revert recent release ([#559](https://github.com/open-feature/open-feature-operator/issues/559)) ([f7c79e4](https://github.com/open-feature/open-feature-operator/commit/f7c79e4c6f5a5dee05d7db1796bfb9891dbd53a0))
## [0.2.37](https://github.com/open-feature/open-feature-operator/compare/apis-v0.2.36...apis/v0.2.37) (2023-11-15)
### ✨ New Features
* Introduce v1beta1 API version ([#535](https://github.com/open-feature/open-feature-operator/issues/535)) ([3acd492](https://github.com/open-feature/open-feature-operator/commit/3acd49289a40e8f07fd20aad46185ac42ceb1b7a))
* release APIs and Operator independently ([#541](https://github.com/open-feature/open-feature-operator/issues/541)) ([7b1af42](https://github.com/open-feature/open-feature-operator/commit/7b1af42ac41e63ccbb1820b31f579ffea679cff6))
### 🧹 Chore
* use github-action for golangci-lint workflow ([#538](https://github.com/open-feature/open-feature-operator/issues/538)) ([a97d336](https://github.com/open-feature/open-feature-operator/commit/a97d336468d5a9b50662f4979784c8388ec10ec1))

View File

@ -17,19 +17,12 @@ limitations under the License.
package v1alpha1
import (
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1/common"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// FeatureFlagConfigurationSpec defines the desired state of FeatureFlagConfiguration
type FeatureFlagConfigurationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// ServiceProvider [DEPRECATED]: superseded by FlagSourceConfiguration
// +optional
// +nullable
@ -78,8 +71,6 @@ type FeatureFlagServiceProvider struct {
// FeatureFlagConfigurationStatus defines the observed state of FeatureFlagConfiguration
type FeatureFlagConfigurationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:object:root=true
@ -107,33 +98,3 @@ type FeatureFlagConfigurationList struct {
func init() {
SchemeBuilder.Register(&FeatureFlagConfiguration{}, &FeatureFlagConfigurationList{})
}
func (ff *FeatureFlagConfiguration) GetReference() metav1.OwnerReference {
return metav1.OwnerReference{
APIVersion: ff.APIVersion,
Kind: ff.Kind,
Name: ff.Name,
UID: ff.UID,
Controller: common.TrueVal(),
}
}
func (ff *FeatureFlagConfiguration) GenerateConfigMap(name string, namespace string, references []metav1.OwnerReference) corev1.ConfigMap {
return corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
"openfeature.dev/featureflagconfiguration": name,
},
OwnerReferences: references,
},
Data: map[string]string{
common.FeatureFlagConfigurationConfigMapKey(namespace, name): ff.Spec.FeatureFlagSpec,
},
}
}
func (p *FeatureFlagServiceProvider) IsSet() bool {
return p != nil && p.Name != ""
}

View File

@ -14,15 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package v1beta1
package v1alpha1
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// FeatureFlagSourceSpec defines the desired state of FeatureFlagSource
type FeatureFlagSourceSpec struct {
type SyncProviderType string
// FlagSourceConfigurationSpec defines the desired state of FlagSourceConfiguration
type FlagSourceConfigurationSpec struct {
// MetricsPort defines the port to serve metrics on, defaults to 8014
// +optional
MetricsPort int32 `json:"metricsPort"`
@ -35,6 +37,10 @@ type FeatureFlagSourceSpec struct {
// +optional
SocketPath string `json:"socketPath"`
// SyncProviderArgs are string arguments passed to all sync providers, defined as key values separated by =
// +optional
SyncProviderArgs []string `json:"syncProviderArgs"`
// Evaluator sets an evaluator, defaults to 'json'
// +optional
Evaluator string `json:"evaluator"`
@ -47,31 +53,27 @@ type FeatureFlagSourceSpec struct {
// +optional
Tag string `json:"tag"`
// SyncProviders define the syncProviders and associated configuration to be applied to the sidecar
// +kubebuilder:validation:MinItems=1
Sources []Source `json:"sources"`
// 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
// +optional
EnvVars []corev1.EnvVar `json:"envVars"`
// SyncProviderArgs are string arguments passed to all sync providers, defined as key values separated by =
// +optional
SyncProviderArgs []string `json:"syncProviderArgs"`
// DefaultSyncProvider defines the default sync provider
// +optional
DefaultSyncProvider SyncProviderType `json:"defaultSyncProvider"`
// LogFormat allows for the sidecar log format to be overridden, defaults to 'json'
// Sources defines the syncProviders and associated configuration to be applied to the sidecar
// +kubebuilder:validation:MinItems=1
Sources []Source `json:"sources"`
// 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
// +optional
LogFormat string `json:"logFormat"`
EnvVars []corev1.EnvVar `json:"envVars"`
// EnvVarPrefix defines the prefix to be applied to all environment variables applied to the sidecar, default FLAGD
// +optional
EnvVarPrefix string `json:"envVarPrefix"`
// LogFormat allows for the sidecar log format to be overridden, defaults to 'json'
// +optional
LogFormat string `json:"logFormat"`
// RolloutOnChange dictates whether annotated deployments will be restarted when configuration changes are
// detected in this CR, defaults to false
// +optional
@ -98,7 +100,7 @@ type Source struct {
// Source is a URI of the flag sources
Source string `json:"source"`
// Provider type - kubernetes, http(s), grpc(s) or filepath
// Provider type - kubernetes, http, grpc or filepath
// +optional
Provider SyncProviderType `json:"provider"`
@ -123,52 +125,33 @@ type Source struct {
Selector string `json:"selector,omitempty"`
}
// FeatureFlagSourceStatus defines the observed state of FeatureFlagSource
type FeatureFlagSourceStatus struct {
// FlagSourceConfigurationStatus defines the observed state of FlagSourceConfiguration
type FlagSourceConfigurationStatus struct {
}
//+kubebuilder:resource:shortName="ffs"
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
// +kubebuilder:resource:shortName="fsc"
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:storageversion
// FeatureFlagSource is the Schema for the FeatureFlagSources API
type FeatureFlagSource struct {
// FlagSourceConfiguration is the Schema for the FlagSourceConfigurations API
type FlagSourceConfiguration struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec FeatureFlagSourceSpec `json:"spec,omitempty"`
Status FeatureFlagSourceStatus `json:"status,omitempty"`
Spec FlagSourceConfigurationSpec `json:"spec,omitempty"`
Status FlagSourceConfigurationStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// +kubebuilder:object:root=true
// FeatureFlagSourceList contains a list of FeatureFlagSource
type FeatureFlagSourceList struct {
// FlagSourceConfigurationList contains a list of FlagSourceConfiguration
type FlagSourceConfigurationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []FeatureFlagSource `json:"items"`
Items []FlagSourceConfiguration `json:"items"`
}
func init() {
SchemeBuilder.Register(&FeatureFlagSource{}, &FeatureFlagSourceList{})
}
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
SchemeBuilder.Register(&FlagSourceConfiguration{}, &FlagSourceConfigurationList{})
}

View File

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

View File

@ -23,14 +23,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// FeatureFlagConfigurationSpec defines the desired state of FeatureFlagConfiguration
type FeatureFlagConfigurationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// ServiceProvider [DEPRECATED]: superseded by FlagSourceConfiguration
// +optional
// +nullable
@ -109,11 +103,9 @@ type FeatureFlagServiceProvider struct {
// FeatureFlagConfigurationStatus defines the observed state of FeatureFlagConfiguration
type FeatureFlagConfigurationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:resource:shortName="ff"
//+kubebuilder:resource:shortName="ffc"
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

View File

@ -20,14 +20,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// FlagSourceConfigurationSpec defines the desired state of FlagSourceConfiguration
type FlagSourceConfigurationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// MetricsPort defines the port to serve metrics on, defaults to 8013
// +optional
MetricsPort int32 `json:"metricsPort"`
@ -75,8 +69,6 @@ type FlagSourceConfigurationSpec struct {
// FlagSourceConfigurationStatus defines the observed state of FlagSourceConfiguration
type FlagSourceConfigurationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:resource:shortName="fsc"

View File

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

View File

@ -23,14 +23,8 @@ import (
type SyncProviderType string
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// FlagSourceConfigurationSpec defines the desired state of FlagSourceConfiguration
type FlagSourceConfigurationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// MetricsPort defines the port to serve metrics on, defaults to 8014
// +optional
MetricsPort int32 `json:"metricsPort"`
@ -133,8 +127,6 @@ type Source struct {
// FlagSourceConfigurationStatus defines the observed state of FlagSourceConfiguration
type FlagSourceConfigurationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
//+kubebuilder:resource:shortName="fsc"

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

@ -19,6 +19,8 @@ package v1beta1
import (
"encoding/json"
"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"
)
@ -29,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
@ -37,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"`
@ -57,10 +64,10 @@ type Flag struct {
type FeatureFlagStatus struct {
}
// TODO change to `ff` when v1alpha* is removed
//+kubebuilder:resource:shortName="ffc"
//+kubebuilder:resource:shortName="ff"
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:storageversion
// FeatureFlag is the Schema for the featureflags API
type FeatureFlag struct {
@ -83,3 +90,33 @@ type FeatureFlagList struct {
func init() {
SchemeBuilder.Register(&FeatureFlag{}, &FeatureFlagList{})
}
func (ff *FeatureFlag) GetReference() metav1.OwnerReference {
return metav1.OwnerReference{
APIVersion: ff.APIVersion,
Kind: ff.Kind,
Name: ff.Name,
UID: ff.UID,
Controller: common.TrueVal(),
}
}
func (ff *FeatureFlag) GenerateConfigMap(name string, namespace string, references []metav1.OwnerReference) (*corev1.ConfigMap, error) {
b, err := json.Marshal(ff.Spec.FlagSpec)
if err != nil {
return nil, err
}
return &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
"openfeature.dev/featureflag": name,
},
OwnerReferences: references,
},
Data: map[string]string{
common.FeatureFlagConfigMapKey(namespace, name): string(b),
},
}, nil
}

View File

@ -1,17 +1,17 @@
package v1alpha1
package v1beta1
import (
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1/common"
"testing"
"github.com/open-feature/open-feature-operator/apis/core/v1beta1/common"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
func Test_FeatureFlagConfiguration(t *testing.T) {
ffConfig := FeatureFlagConfiguration{
func Test_FeatureFlag(t *testing.T) {
ff := FeatureFlag{
ObjectMeta: v1.ObjectMeta{
Name: "ffconf1",
Namespace: "test",
@ -25,11 +25,21 @@ func Test_FeatureFlagConfiguration(t *testing.T) {
},
},
},
Spec: FeatureFlagConfigurationSpec{
FeatureFlagSpec: "spec",
Spec: FeatureFlagSpec{
FlagSpec: FlagSpec{
Flags: Flags{},
},
},
}
require.Equal(t, v1.OwnerReference{
APIVersion: ff.APIVersion,
Kind: ff.Kind,
Name: ff.Name,
UID: ff.UID,
Controller: common.TrueVal(),
}, ff.GetReference())
name := "cmname"
namespace := "cmnamespace"
references := []v1.OwnerReference{
@ -42,39 +52,19 @@ func Test_FeatureFlagConfiguration(t *testing.T) {
},
}
require.Equal(t, v1.OwnerReference{
APIVersion: ffConfig.APIVersion,
Kind: ffConfig.Kind,
Name: ffConfig.Name,
UID: ffConfig.UID,
Controller: common.TrueVal(),
}, ffConfig.GetReference())
cm, _ := ff.GenerateConfigMap(name, namespace, references)
require.Equal(t, corev1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
"openfeature.dev/featureflagconfiguration": name,
"openfeature.dev/featureflag": name,
},
OwnerReferences: references,
},
Data: map[string]string{
"cmnamespace_cmname.flagd.json": "spec",
"cmnamespace_cmname.flagd.json": "{\"flags\":null}",
},
}, ffConfig.GenerateConfigMap(name, namespace, references))
require.False(t, ffConfig.Spec.ServiceProvider.IsSet())
ffConfig.Spec.ServiceProvider = &FeatureFlagServiceProvider{
Name: "",
}
require.False(t, ffConfig.Spec.ServiceProvider.IsSet())
ffConfig.Spec.ServiceProvider = &FeatureFlagServiceProvider{
Name: "prov",
}
require.True(t, ffConfig.Spec.ServiceProvider.IsSet())
}, *cm)
}

View File

@ -0,0 +1,257 @@
/*
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"
)
// 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
// +optional
SocketPath string `json:"socketPath"`
// 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
// +kubebuilder:validation:MinItems=1
Sources []Source `json:"sources"`
// 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
// +optional
EnvVars []corev1.EnvVar `json:"envVars"`
// SyncProviderArgs are string arguments passed to all sync providers, defined as key values separated by =
// +optional
SyncProviderArgs []string `json:"syncProviderArgs"`
// DefaultSyncProvider defines the default sync provider
// +optional
DefaultSyncProvider common.SyncProviderType `json:"defaultSyncProvider"`
// 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
// detected in this CR, defaults to false
// +optional
RolloutOnChange *bool `json:"rolloutOnChange"`
// ProbesEnabled defines whether to enable liveness and readiness probes of flagd sidecar. Default true (enabled).
// +optional
ProbesEnabled *bool `json:"probesEnabled"`
// DebugLogging defines whether to enable --debug flag of flagd sidecar. Default false (disabled).
// +optional
DebugLogging *bool `json:"debugLogging"`
// OtelCollectorUri defines whether to enable --otel-collector-uri flag of flagd sidecar. Default false (disabled).
// +optional
OtelCollectorUri string `json:"otelCollectorUri"`
// Resources defines flagd sidecar resources. Default to operator sidecar-cpu-* and sidecar-ram-* flags.
// +optional
Resources corev1.ResourceRequirements `json:"resources"`
}
type Source struct {
// Source is a URI of the flag sources
Source string `json:"source"`
// Provider type - kubernetes, http(s), grpc(s) or file
// +optional
Provider common.SyncProviderType `json:"provider"`
// HttpSyncBearerToken is a bearer token. Used by http(s) sync provider only
// +optional
HttpSyncBearerToken string `json:"httpSyncBearerToken"`
// TLS - Enable/Disable secure TLS connectivity. Currently used only by GRPC sync
// +optional
TLS bool `json:"tls"`
// CertPath is a path of a certificate to be used by grpc TLS connection
// +optional
CertPath string `json:"certPath"`
// ProviderID is an identifier to be used in grpc provider
// +optional
ProviderID string `json:"providerID"`
// Selector is a flag configuration selector used by grpc provider
// +optional
Selector string `json:"selector,omitempty"`
// Interval is a flag configuration interval in seconds used by http provider
// +optional
Interval uint32 `json:"interval,omitempty"`
}
// FeatureFlagSourceStatus defines the observed state of FeatureFlagSource
type FeatureFlagSourceStatus struct {
}
//+kubebuilder:resource:shortName="ffs"
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status
//+kubebuilder:storageversion
// FeatureFlagSource is the Schema for the FeatureFlagSources API
type FeatureFlagSource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec FeatureFlagSourceSpec `json:"spec,omitempty"`
Status FeatureFlagSourceStatus `json:"status,omitempty"`
}
//+kubebuilder:object:root=true
// FeatureFlagSourceList contains a list of FeatureFlagSource
type FeatureFlagSourceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []FeatureFlagSource `json:"items"`
}
func init() {
SchemeBuilder.Register(&FeatureFlagSource{}, &FeatureFlagSourceList{})
}
//nolint:gocyclo
func (fc *FeatureFlagSourceSpec) Merge(new *FeatureFlagSourceSpec) {
if new == nil {
return
}
if new.ManagementPort != 0 {
fc.ManagementPort = new.ManagementPort
}
if new.Port != 0 {
fc.Port = new.Port
}
if new.SocketPath != "" {
fc.SocketPath = new.SocketPath
}
if new.Evaluator != "" {
fc.Evaluator = new.Evaluator
}
if len(new.Sources) != 0 {
fc.Sources = append(fc.Sources, new.Sources...)
}
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
}
if new.DefaultSyncProvider != "" {
fc.DefaultSyncProvider = new.DefaultSyncProvider
}
if new.LogFormat != "" {
fc.LogFormat = new.LogFormat
}
if new.RolloutOnChange != nil {
fc.RolloutOnChange = new.RolloutOnChange
}
if new.ProbesEnabled != nil {
fc.ProbesEnabled = new.ProbesEnabled
}
if new.DebugLogging != nil {
fc.DebugLogging = new.DebugLogging
}
if new.OtelCollectorUri != "" {
fc.OtelCollectorUri = new.OtelCollectorUri
}
}
func (fc *FeatureFlagSourceSpec) 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.ManagementPortEnvVar),
Value: fmt.Sprintf("%d", fc.ManagementPort),
})
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.EvaluatorEnvVar),
Value: fc.Evaluator,
})
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, common.SocketPathEnvVar),
Value: fc.SocketPath,
})
}
return envs
}

View File

@ -0,0 +1,227 @@
package v1beta1
import (
"testing"
"github.com/open-feature/open-feature-operator/apis/core/v1beta1/common"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
)
func Test_FLagSourceConfiguration_Merge(t *testing.T) {
ff_old := &FeatureFlagSource{
Spec: FeatureFlagSourceSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
ManagementPort: 22,
Port: 33,
Evaluator: "evaluator",
SocketPath: "socket-path",
LogFormat: "log",
Sources: []Source{
{
Source: "src1",
Provider: common.SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
Interval: 5,
},
},
SyncProviderArgs: []string{"arg1", "arg2"},
DefaultSyncProvider: common.SyncProviderKubernetes,
RolloutOnChange: common.TrueVal(),
ProbesEnabled: common.TrueVal(),
DebugLogging: common.TrueVal(),
OtelCollectorUri: "",
},
}
ff_old.Spec.Merge(nil)
require.Equal(t, &FeatureFlagSource{
Spec: FeatureFlagSourceSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
ManagementPort: 22,
Port: 33,
Evaluator: "evaluator",
SocketPath: "socket-path",
LogFormat: "log",
Sources: []Source{
{
Source: "src1",
Provider: common.SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
Interval: 5,
},
},
SyncProviderArgs: []string{"arg1", "arg2"},
DefaultSyncProvider: common.SyncProviderKubernetes,
RolloutOnChange: common.TrueVal(),
ProbesEnabled: common.TrueVal(),
DebugLogging: common.TrueVal(),
OtelCollectorUri: "",
},
}, ff_old)
ff_new := &FeatureFlagSource{
Spec: FeatureFlagSourceSpec{
EnvVars: []v1.EnvVar{
{
Name: "env3",
Value: "val3",
},
{
Name: "env4",
Value: "val4",
},
},
EnvVarPrefix: "PREFIX",
ManagementPort: 221,
Port: 331,
Evaluator: "evaluator1",
SocketPath: "socket-path1",
LogFormat: "log1",
Sources: []Source{
{
Source: "src2",
Provider: common.SyncProviderFilepath,
},
},
SyncProviderArgs: []string{"arg3", "arg4"},
DefaultSyncProvider: common.SyncProviderFilepath,
RolloutOnChange: common.FalseVal(),
ProbesEnabled: common.FalseVal(),
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
}
ff_old.Spec.Merge(&ff_new.Spec)
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,
},
{
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) {
ff := FeatureFlagSource{
Spec: FeatureFlagSourceSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
ManagementPort: 22,
Port: 33,
Evaluator: "evaluator",
SocketPath: "socket-path",
LogFormat: "log",
},
}
expected := []v1.EnvVar{
{
Name: "PRE_env1",
Value: "val1",
},
{
Name: "PRE_env2",
Value: "val2",
},
{
Name: "PRE_MANAGEMENT_PORT",
Value: "22",
},
{
Name: "PRE_PORT",
Value: "33",
},
{
Name: "PRE_EVALUATOR",
Value: "evaluator",
},
{
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,14 +0,0 @@
# Changelog
## [0.2.37](https://github.com/open-feature/open-feature-operator/compare/apis-v0.2.36...apis/v0.2.37) (2023-11-15)
### ✨ New Features
* Introduce v1beta1 API version ([#535](https://github.com/open-feature/open-feature-operator/issues/535)) ([3acd492](https://github.com/open-feature/open-feature-operator/commit/3acd49289a40e8f07fd20aad46185ac42ceb1b7a))
* release APIs and Operator independently ([#541](https://github.com/open-feature/open-feature-operator/issues/541)) ([7b1af42](https://github.com/open-feature/open-feature-operator/commit/7b1af42ac41e63ccbb1820b31f579ffea679cff6))
### 🧹 Chore
* use github-action for golangci-lint workflow ([#538](https://github.com/open-feature/open-feature-operator/issues/538)) ([a97d336](https://github.com/open-feature/open-feature-operator/commit/a97d336468d5a9b50662f4979784c8388ec10ec1))

View File

@ -1,23 +0,0 @@
package common
import "fmt"
func TrueVal() *bool {
b := true
return &b
}
func FalseVal() *bool {
b := false
return &b
}
// unique string used to create unique volume mount and file name
func FeatureFlagConfigurationId(namespace, name string) string {
return fmt.Sprintf("%s_%s", namespace, name)
}
// unique key (and filename) for configMap data
func FeatureFlagConfigurationConfigMapKey(namespace, name string) string {
return fmt.Sprintf("%s.flagd.json", FeatureFlagConfigurationId(namespace, name))
}

View File

@ -1,20 +0,0 @@
/*
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 v1alpha1
// Hub marks this type as a conversion hub.
func (ffc *FeatureFlagConfiguration) Hub() {}

View File

@ -1,9 +0,0 @@
package v1alpha1
import ctrl "sigs.k8s.io/controller-runtime"
func (r *FeatureFlagConfiguration) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}

View File

@ -1,20 +0,0 @@
/*
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 v1alpha1
// Hub marks this type as a conversion hub.
func (ffc *FlagSourceConfiguration) Hub() {}

View File

@ -1,411 +0,0 @@
/*
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 v1alpha1
import (
"fmt"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1/common"
"os"
"strconv"
"strings"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type SyncProviderType string
const (
SidecarEnvVarPrefix string = "SIDECAR_ENV_VAR_PREFIX"
InputConfigurationEnvVarPrefix string = "SIDECAR"
SidecarMetricPortEnvVar string = "METRICS_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"
DefaultMetricPort int32 = 8014
defaultPort int32 = 8013
defaultSocketPath string = ""
defaultEvaluator string = "json"
defaultImage string = "ghcr.io/open-feature/flagd"
// renovate: datasource=github-tags depName=open-feature/flagd/flagd
defaultTag string = "v0.6.3"
defaultLogFormat string = "json"
defaultProbesEnabled bool = true
SyncProviderKubernetes SyncProviderType = "kubernetes"
SyncProviderFilepath SyncProviderType = "filepath"
SyncProviderHttp SyncProviderType = "http"
SyncProviderGrpc SyncProviderType = "grpc"
SyncProviderFlagdProxy SyncProviderType = "flagd-proxy"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// FlagSourceConfigurationSpec defines the desired state of FlagSourceConfiguration
type FlagSourceConfigurationSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
// MetricsPort defines the port to serve metrics on, defaults to 8014
// +optional
MetricsPort int32 `json:"metricsPort"`
// Port defines the port to listen on, defaults to 8013
// +optional
Port int32 `json:"port"`
// SocketPath defines the unix socket path to listen on
// +optional
SocketPath string `json:"socketPath"`
// SyncProviderArgs are string arguments passed to all sync providers, defined as key values separated by =
// +optional
SyncProviderArgs []string `json:"syncProviderArgs"`
// Evaluator sets an evaluator, defaults to 'json'
// +optional
Evaluator string `json:"evaluator"`
// Image allows for the sidecar image to be overridden, defaults to 'ghcr.io/open-feature/flagd'
// +optional
Image string `json:"image"`
// Tag to be appended to the sidecar image, defaults to 'main'
// +optional
Tag string `json:"tag"`
// DefaultSyncProvider defines the default sync provider
// +optional
DefaultSyncProvider SyncProviderType `json:"defaultSyncProvider"`
// Sources defines the syncProviders and associated configuration to be applied to the sidecar
// +kubebuilder:validation:MinItems=1
Sources []Source `json:"sources"`
// 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
// +optional
EnvVars []corev1.EnvVar `json:"envVars"`
// EnvVarPrefix defines the prefix to be applied to all environment variables applied to the sidecar, default FLAGD
// +optional
EnvVarPrefix string `json:"envVarPrefix"`
// LogFormat allows for the sidecar log format to be overridden, defaults to 'json'
// +optional
LogFormat string `json:"logFormat"`
// RolloutOnChange dictates whether annotated deployments will be restarted when configuration changes are
// detected in this CR, defaults to false
// +optional
RolloutOnChange *bool `json:"rolloutOnChange"`
// ProbesEnabled defines whether to enable liveness and readiness probes of flagd sidecar. Default true (enabled).
// +optional
ProbesEnabled *bool `json:"probesEnabled"`
// DebugLogging defines whether to enable --debug flag of flagd sidecar. Default false (disabled).
// +optional
DebugLogging *bool `json:"debugLogging"`
// OtelCollectorUri defines whether to enable --otel-collector-uri flag of flagd sidecar. Default false (disabled).
// +optional
OtelCollectorUri string `json:"otelCollectorUri"`
// Resources defines flagd sidecar resources. Default to operator sidecar-cpu-* and sidecar-ram-* flags.
// +optional
Resources corev1.ResourceRequirements `json:"resources"`
}
type Source struct {
// Source is a URI of the flag sources
Source string `json:"source"`
// Provider type - kubernetes, http, grpc or filepath
// +optional
Provider SyncProviderType `json:"provider"`
// HttpSyncBearerToken is a bearer token. Used by http(s) sync provider only
// +optional
HttpSyncBearerToken string `json:"httpSyncBearerToken"`
// TLS - Enable/Disable secure TLS connectivity. Currently used only by GRPC sync
// +optional
TLS bool `json:"tls"`
// CertPath is a path of a certificate to be used by grpc TLS connection
// +optional
CertPath string `json:"certPath"`
// ProviderID is an identifier to be used in grpc provider
// +optional
ProviderID string `json:"providerID"`
// Selector is a flag configuration selector used by grpc provider
// +optional
Selector string `json:"selector,omitempty"`
}
// FlagSourceConfigurationStatus defines the observed state of FlagSourceConfiguration
type FlagSourceConfigurationStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}
// +kubebuilder:resource:shortName="fsc"
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:storageversion
// FlagSourceConfiguration is the Schema for the FlagSourceConfigurations API
type FlagSourceConfiguration struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec FlagSourceConfigurationSpec `json:"spec,omitempty"`
Status FlagSourceConfigurationStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// FlagSourceConfigurationList contains a list of FlagSourceConfiguration
type FlagSourceConfigurationList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []FlagSourceConfiguration `json:"items"`
}
//nolint:gocyclo
func NewFlagSourceConfigurationSpec() (*FlagSourceConfigurationSpec, error) {
fsc := &FlagSourceConfigurationSpec{
MetricsPort: DefaultMetricPort,
Port: defaultPort,
SocketPath: defaultSocketPath,
Evaluator: defaultEvaluator,
Image: defaultImage,
Tag: defaultTag,
Sources: []Source{},
EnvVars: []corev1.EnvVar{},
SyncProviderArgs: []string{},
DefaultSyncProvider: SyncProviderKubernetes,
EnvVarPrefix: defaultSidecarEnvVarPrefix,
LogFormat: defaultLogFormat,
RolloutOnChange: nil,
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
}
// set default value derived from constant default
probes := defaultProbesEnabled
fsc.ProbesEnabled = &probes
if metricsPort := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarMetricPortEnvVar)); metricsPort != "" {
metricsPortI, err := strconv.Atoi(metricsPort)
if err != nil {
return fsc, fmt.Errorf("unable to parse metrics port value %s to int32: %w", metricsPort, err)
}
fsc.MetricsPort = int32(metricsPortI)
}
if port := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarPortEnvVar)); port != "" {
portI, err := strconv.Atoi(port)
if err != nil {
return fsc, fmt.Errorf("unable to parse sidecar port value %s to int32: %w", port, err)
}
fsc.Port = int32(portI)
}
if socketPath := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarSocketPathEnvVar)); socketPath != "" {
fsc.SocketPath = socketPath
}
if evaluator := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarEvaluatorEnvVar)); evaluator != "" {
fsc.Evaluator = evaluator
}
if image := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarImageEnvVar)); image != "" {
fsc.Image = image
}
if tag := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarVersionEnvVar)); tag != "" {
fsc.Tag = tag
}
if syncProviderArgs := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProviderArgsEnvVar)); syncProviderArgs != "" {
fsc.SyncProviderArgs = strings.Split(syncProviderArgs, ",") // todo: add documentation for this
}
if syncProvider := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarDefaultSyncProviderEnvVar)); syncProvider != "" {
fsc.DefaultSyncProvider = SyncProviderType(syncProvider)
}
if logFormat := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarLogFormatEnvVar)); logFormat != "" {
fsc.LogFormat = logFormat
}
if envVarPrefix := os.Getenv(SidecarEnvVarPrefix); envVarPrefix != "" {
fsc.EnvVarPrefix = envVarPrefix
}
if probesEnabled := os.Getenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProbesEnabledVar)); probesEnabled != "" {
b, err := strconv.ParseBool(probesEnabled)
if err != nil {
return fsc, fmt.Errorf("unable to parse sidecar probes enabled %s to boolean: %w", probesEnabled, err)
}
fsc.ProbesEnabled = &b
}
return fsc, nil
}
//nolint:gocyclo
func (fc *FlagSourceConfigurationSpec) Merge(new *FlagSourceConfigurationSpec) {
if new == nil {
return
}
if new.MetricsPort != 0 {
fc.MetricsPort = new.MetricsPort
}
if new.Port != 0 {
fc.Port = new.Port
}
if new.SocketPath != "" {
fc.SocketPath = new.SocketPath
}
if new.Evaluator != "" {
fc.Evaluator = new.Evaluator
}
if new.Image != "" {
fc.Image = new.Image
}
if new.Tag != "" {
fc.Tag = new.Tag
}
if len(new.Sources) != 0 {
fc.Sources = append(fc.Sources, new.Sources...)
}
if len(new.EnvVars) != 0 {
fc.EnvVars = append(fc.EnvVars, new.EnvVars...)
}
if new.SyncProviderArgs != nil && len(new.SyncProviderArgs) > 0 {
fc.SyncProviderArgs = append(fc.SyncProviderArgs, new.SyncProviderArgs...)
}
if new.EnvVarPrefix != "" {
fc.EnvVarPrefix = new.EnvVarPrefix
}
if new.DefaultSyncProvider != "" {
fc.DefaultSyncProvider = new.DefaultSyncProvider
}
if new.LogFormat != "" {
fc.LogFormat = new.LogFormat
}
if new.RolloutOnChange != nil {
fc.RolloutOnChange = new.RolloutOnChange
}
if new.ProbesEnabled != nil {
fc.ProbesEnabled = new.ProbesEnabled
}
if new.DebugLogging != nil {
fc.DebugLogging = new.DebugLogging
}
if new.OtelCollectorUri != "" {
fc.OtelCollectorUri = new.OtelCollectorUri
}
}
func (fc *FlagSourceConfigurationSpec) ToEnvVars() []corev1.EnvVar {
envs := []corev1.EnvVar{}
for _, envVar := range fc.EnvVars {
envs = append(envs, corev1.EnvVar{
Name: envVarKey(fc.EnvVarPrefix, envVar.Name),
Value: envVar.Value,
})
}
if fc.MetricsPort != DefaultMetricPort {
envs = append(envs, corev1.EnvVar{
Name: envVarKey(fc.EnvVarPrefix, SidecarMetricPortEnvVar),
Value: fmt.Sprintf("%d", fc.MetricsPort),
})
}
if fc.Port != defaultPort {
envs = append(envs, corev1.EnvVar{
Name: envVarKey(fc.EnvVarPrefix, SidecarPortEnvVar),
Value: fmt.Sprintf("%d", fc.Port),
})
}
if fc.Evaluator != defaultEvaluator {
envs = append(envs, corev1.EnvVar{
Name: envVarKey(fc.EnvVarPrefix, SidecarEvaluatorEnvVar),
Value: fc.Evaluator,
})
}
if fc.SocketPath != defaultSocketPath {
envs = append(envs, corev1.EnvVar{
Name: envVarKey(fc.EnvVarPrefix, SidecarSocketPathEnvVar),
Value: fc.SocketPath,
})
}
if fc.LogFormat != defaultLogFormat {
envs = append(envs, corev1.EnvVar{
Name: envVarKey(fc.EnvVarPrefix, SidecarLogFormatEnvVar),
Value: fc.LogFormat,
})
}
return envs
}
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 envVarKey(prefix string, suffix string) string {
return fmt.Sprintf("%s_%s", prefix, suffix)
}
func init() {
SchemeBuilder.Register(&FlagSourceConfiguration{}, &FlagSourceConfigurationList{})
}

View File

@ -1,303 +0,0 @@
package v1alpha1
import (
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1/common"
"testing"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
)
func Test_FLagSourceConfiguration_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_ToEnvVars(t *testing.T) {
ff := FlagSourceConfiguration{
Spec: FlagSourceConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
MetricsPort: 22,
Port: 33,
Evaluator: "evaluator",
SocketPath: "socket-path",
LogFormat: "log",
},
}
expected := []v1.EnvVar{
{
Name: "PRE_env1",
Value: "val1",
},
{
Name: "PRE_env2",
Value: "val2",
},
{
Name: "PRE_METRICS_PORT",
Value: "22",
},
{
Name: "PRE_PORT",
Value: "33",
},
{
Name: "PRE_EVALUATOR",
Value: "evaluator",
},
{
Name: "PRE_SOCKET_PATH",
Value: "socket-path",
},
{
Name: "PRE_LOG_FORMAT",
Value: "log",
},
}
require.Equal(t, expected, ff.Spec.ToEnvVars())
}
func Test_FLagSourceConfiguration_Merge(t *testing.T) {
ff_old := &FlagSourceConfiguration{
Spec: FlagSourceConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
MetricsPort: 22,
Port: 33,
Evaluator: "evaluator",
SocketPath: "socket-path",
LogFormat: "log",
Image: "img",
Tag: "tag",
Sources: []Source{
{
Source: "src1",
Provider: SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
},
SyncProviderArgs: []string{"arg1", "arg2"},
DefaultSyncProvider: SyncProviderKubernetes,
RolloutOnChange: common.TrueVal(),
ProbesEnabled: common.TrueVal(),
DebugLogging: common.TrueVal(),
OtelCollectorUri: "",
},
}
ff_old.Spec.Merge(nil)
require.Equal(t, &FlagSourceConfiguration{
Spec: FlagSourceConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
EnvVarPrefix: "PRE",
MetricsPort: 22,
Port: 33,
Evaluator: "evaluator",
SocketPath: "socket-path",
LogFormat: "log",
Image: "img",
Tag: "tag",
Sources: []Source{
{
Source: "src1",
Provider: SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
},
SyncProviderArgs: []string{"arg1", "arg2"},
DefaultSyncProvider: SyncProviderKubernetes,
RolloutOnChange: common.TrueVal(),
ProbesEnabled: common.TrueVal(),
DebugLogging: common.TrueVal(),
OtelCollectorUri: "",
},
}, ff_old)
ff_new := &FlagSourceConfiguration{
Spec: FlagSourceConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env3",
Value: "val3",
},
{
Name: "env4",
Value: "val4",
},
},
EnvVarPrefix: "PREFIX",
MetricsPort: 221,
Port: 331,
Evaluator: "evaluator1",
SocketPath: "socket-path1",
LogFormat: "log1",
Image: "img1",
Tag: "tag1",
Sources: []Source{
{
Source: "src2",
Provider: SyncProviderFilepath,
},
},
SyncProviderArgs: []string{"arg3", "arg4"},
DefaultSyncProvider: SyncProviderFilepath,
RolloutOnChange: common.FalseVal(),
ProbesEnabled: common.FalseVal(),
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
}
ff_old.Spec.Merge(&ff_new.Spec)
require.Equal(t, &FlagSourceConfiguration{
Spec: FlagSourceConfigurationSpec{
EnvVars: []v1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
{
Name: "env3",
Value: "val3",
},
{
Name: "env4",
Value: "val4",
},
},
EnvVarPrefix: "PREFIX",
MetricsPort: 221,
Port: 331,
Evaluator: "evaluator1",
SocketPath: "socket-path1",
LogFormat: "log1",
Image: "img1",
Tag: "tag1",
Sources: []Source{
{
Source: "src1",
Provider: SyncProviderGrpc,
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
{
Source: "src2",
Provider: SyncProviderFilepath,
},
},
SyncProviderArgs: []string{"arg1", "arg2", "arg3", "arg4"},
DefaultSyncProvider: SyncProviderFilepath,
RolloutOnChange: common.FalseVal(),
ProbesEnabled: common.FalseVal(),
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
}, ff_old)
}
func Test_FLagSourceConfiguration_NewFlagSourceConfigurationSpec(t *testing.T) {
//happy path
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarMetricPortEnvVar), "22")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarPortEnvVar), "33")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarSocketPathEnvVar), "val1")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarEvaluatorEnvVar), "val2")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarImageEnvVar), "val3")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarVersionEnvVar), "val4")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProviderArgsEnvVar), "val11,val22")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarDefaultSyncProviderEnvVar), "kubernetes")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarLogFormatEnvVar), "val5")
t.Setenv(SidecarEnvVarPrefix, "val6")
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProbesEnabledVar), "true")
fs, err := NewFlagSourceConfigurationSpec()
require.Nil(t, err)
require.Equal(t, &FlagSourceConfigurationSpec{
MetricsPort: 22,
Port: 33,
SocketPath: "val1",
Evaluator: "val2",
Image: "val3",
Tag: "val4",
Sources: []Source{},
EnvVars: []v1.EnvVar{},
SyncProviderArgs: []string{"val11", "val22"},
DefaultSyncProvider: SyncProviderKubernetes,
EnvVarPrefix: "val6",
LogFormat: "val5",
ProbesEnabled: common.TrueVal(),
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
}, fs)
//error paths
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProbesEnabledVar), "blah")
_, err = NewFlagSourceConfigurationSpec()
require.NotNil(t, err)
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarPortEnvVar), "blah")
_, err = NewFlagSourceConfigurationSpec()
require.NotNil(t, err)
t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarMetricPortEnvVar), "blah")
_, err = NewFlagSourceConfigurationSpec()
require.NotNil(t, err)
}

View File

@ -1,11 +0,0 @@
package v1alpha1
import (
ctrl "sigs.k8s.io/controller-runtime"
)
func (r *FlagSourceConfiguration) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
Complete()
}

View File

@ -1,16 +0,0 @@
package common
import "errors"
var ErrCannotCastFlagSourceConfiguration = errors.New("cannot cast FlagSourceConfiguration to v1alpha2")
var ErrCannotCastFeatureFlagConfiguration = errors.New("cannot cast FeatureFlagConfiguration to v1alpha2")
func TrueVal() *bool {
b := true
return &b
}
func FalseVal() *bool {
b := false
return &b
}

View File

@ -1,112 +0,0 @@
/*
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 v1alpha2
import (
"encoding/json"
"fmt"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha2/common"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)
func (src *FeatureFlagConfiguration) ConvertTo(dstRaw conversion.Hub) error {
dst, ok := dstRaw.(*v1alpha1.FeatureFlagConfiguration)
if !ok {
return fmt.Errorf("type %T %w", dstRaw, common.ErrCannotCastFeatureFlagConfiguration)
}
// Copy equal stuff to new object
// DO NOT COPY TypeMeta
dst.ObjectMeta = src.ObjectMeta
if src.Spec.ServiceProvider != nil {
dst.Spec.ServiceProvider = &v1alpha1.FeatureFlagServiceProvider{
Name: src.Spec.ServiceProvider.Name,
Credentials: src.Spec.ServiceProvider.Credentials,
}
}
if src.Spec.SyncProvider != nil {
dst.Spec.SyncProvider = &v1alpha1.FeatureFlagSyncProvider{Name: src.Spec.SyncProvider.Name}
if src.Spec.SyncProvider.HttpSyncConfiguration != nil {
dst.Spec.SyncProvider.HttpSyncConfiguration = &v1alpha1.HttpSyncConfiguration{
Target: src.Spec.SyncProvider.HttpSyncConfiguration.Target,
BearerToken: src.Spec.SyncProvider.HttpSyncConfiguration.BearerToken,
}
}
}
if src.Spec.FlagDSpec != nil {
dst.Spec.FlagDSpec = &v1alpha1.FlagDSpec{Envs: src.Spec.FlagDSpec.Envs}
}
featureFlagSpecB, err := json.Marshal(src.Spec.FeatureFlagSpec)
if err != nil {
return fmt.Errorf("featureflagspec: %w", err)
}
dst.Spec.FeatureFlagSpec = string(featureFlagSpecB)
return nil
}
func (dst *FeatureFlagConfiguration) ConvertFrom(srcRaw conversion.Hub) error {
src, ok := srcRaw.(*v1alpha1.FeatureFlagConfiguration)
if !ok {
return fmt.Errorf("type %T %w", srcRaw, common.ErrCannotCastFeatureFlagConfiguration)
}
// Copy equal stuff to new object
// DO NOT COPY TypeMeta
dst.ObjectMeta = src.ObjectMeta
if src.Spec.ServiceProvider != nil {
dst.Spec.ServiceProvider = &FeatureFlagServiceProvider{
Name: src.Spec.ServiceProvider.Name,
Credentials: src.Spec.ServiceProvider.Credentials,
}
}
if src.Spec.SyncProvider != nil {
dst.Spec.SyncProvider = &FeatureFlagSyncProvider{
Name: string(src.Spec.SyncProvider.Name),
}
if src.Spec.SyncProvider.HttpSyncConfiguration != nil {
dst.Spec.SyncProvider.HttpSyncConfiguration = &HttpSyncConfiguration{
Target: src.Spec.SyncProvider.HttpSyncConfiguration.Target,
BearerToken: src.Spec.SyncProvider.HttpSyncConfiguration.BearerToken,
}
}
}
if src.Spec.FlagDSpec != nil {
dst.Spec.FlagDSpec = &FlagDSpec{Envs: src.Spec.FlagDSpec.Envs}
}
var featureFlagSpec FeatureFlagSpec
if err := json.Unmarshal([]byte(src.Spec.FeatureFlagSpec), &featureFlagSpec); err != nil {
return fmt.Errorf("featureflagspec: %w", err)
}
dst.Spec.FeatureFlagSpec = featureFlagSpec
return nil
}

View File

@ -1,318 +0,0 @@
package v1alpha2
import (
"testing"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha2/common"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "sigs.k8s.io/controller-runtime/pkg/webhook/conversion/testdata/api/v2"
)
func TestFeatureFlagConfiguration_ConvertFrom(t *testing.T) {
tests := []struct {
name string
srcObj *v1alpha1.FeatureFlagConfiguration
wantErr bool
wantObj *FeatureFlagConfiguration
}{
{
name: "Test that conversion from v1alpha1 to v1alpha2 works",
srcObj: &v1alpha1.FeatureFlagConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FeatureFlagConfiguration",
APIVersion: "core.openfeature.dev/v1alpha1",
},
ObjectMeta: v1.ObjectMeta{
Name: "FeatureFlagconfig1",
Namespace: "default",
},
Spec: v1alpha1.FeatureFlagConfigurationSpec{
ServiceProvider: &v1alpha1.FeatureFlagServiceProvider{
Name: "name1",
Credentials: &corev1.ObjectReference{
Kind: "Pod",
Namespace: "default",
Name: "pod1",
},
},
SyncProvider: &v1alpha1.FeatureFlagSyncProvider{
Name: "syncprovider1",
HttpSyncConfiguration: &v1alpha1.HttpSyncConfiguration{
Target: "target1",
BearerToken: "token",
},
},
FlagDSpec: &v1alpha1.FlagDSpec{
MetricsPort: 22,
Envs: []corev1.EnvVar{
{
Name: "var1",
Value: "val1",
},
{
Name: "var2",
Value: "val2",
},
},
},
FeatureFlagSpec: `{"flags":{"flag1":{"state":"ok","variants":"variant1","defaultVariant":"default"}}}`,
},
},
wantErr: false,
wantObj: &FeatureFlagConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: "FeatureFlagconfig1",
Namespace: "default",
},
Spec: FeatureFlagConfigurationSpec{
ServiceProvider: &FeatureFlagServiceProvider{
Name: "name1",
Credentials: &corev1.ObjectReference{
Kind: "Pod",
Namespace: "default",
Name: "pod1",
},
},
SyncProvider: &FeatureFlagSyncProvider{
Name: "syncprovider1",
HttpSyncConfiguration: &HttpSyncConfiguration{
Target: "target1",
BearerToken: "token",
},
},
FlagDSpec: &FlagDSpec{
Envs: []corev1.EnvVar{
{
Name: "var1",
Value: "val1",
},
{
Name: "var2",
Value: "val2",
},
},
},
FeatureFlagSpec: FeatureFlagSpec{
Flags: map[string]FlagSpec{
"flag1": {
State: "ok",
DefaultVariant: "default",
Variants: []byte(`"variant1"`),
},
},
},
},
},
},
{
name: "unable to unmarshal featureflagspec json",
srcObj: &v1alpha1.FeatureFlagConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FeatureFlagConfiguration",
APIVersion: "core.openfeature.dev/v1alpha1",
},
ObjectMeta: v1.ObjectMeta{
Name: "FeatureFlagconfig1",
Namespace: "default",
},
Spec: v1alpha1.FeatureFlagConfigurationSpec{
ServiceProvider: &v1alpha1.FeatureFlagServiceProvider{
Name: "name1",
Credentials: &corev1.ObjectReference{
Kind: "Pod",
Namespace: "default",
Name: "pod1",
},
},
SyncProvider: &v1alpha1.FeatureFlagSyncProvider{
Name: "syncprovider1",
HttpSyncConfiguration: &v1alpha1.HttpSyncConfiguration{
Target: "target1",
BearerToken: "token",
},
},
FlagDSpec: &v1alpha1.FlagDSpec{
MetricsPort: 22,
Envs: []corev1.EnvVar{
{
Name: "var1",
Value: "val1",
},
{
Name: "var2",
Value: "val2",
},
},
},
FeatureFlagSpec: `invalid`,
},
},
wantErr: true,
wantObj: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dst := &FeatureFlagConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: FeatureFlagConfigurationSpec{},
Status: FeatureFlagConfigurationStatus{},
}
if err := dst.ConvertFrom(tt.srcObj); (err != nil) != tt.wantErr {
t.Errorf("ConvertFrom() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantObj != nil {
require.Equal(t, tt.wantObj, dst, "Object was not converted correctly")
}
})
}
}
func TestFeatureFlagConfiguration_ConvertTo(t *testing.T) {
tests := []struct {
name string
src *FeatureFlagConfiguration
wantErr bool
wantObj *v1alpha1.FeatureFlagConfiguration
}{
{
name: "Test that conversion from v1alpha2 to v1alpha1 works",
src: &FeatureFlagConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FeatureFlagConfiguration",
APIVersion: "core.openfeature.dev/v1alpha2",
},
ObjectMeta: v1.ObjectMeta{
Name: "FeatureFlagconfig1",
Namespace: "default",
},
Spec: FeatureFlagConfigurationSpec{
ServiceProvider: &FeatureFlagServiceProvider{
Name: "name1",
Credentials: &corev1.ObjectReference{
Kind: "Pod",
Namespace: "default",
Name: "pod1",
},
},
SyncProvider: &FeatureFlagSyncProvider{
Name: "syncprovider1",
HttpSyncConfiguration: &HttpSyncConfiguration{
Target: "target1",
BearerToken: "token",
},
},
FlagDSpec: &FlagDSpec{
Envs: []corev1.EnvVar{
{
Name: "var1",
Value: "val1",
},
{
Name: "var2",
Value: "val2",
},
},
},
FeatureFlagSpec: FeatureFlagSpec{
Flags: map[string]FlagSpec{
"flag1": {
State: "ok",
DefaultVariant: "default",
Variants: []byte(`"variant1"`),
},
},
},
},
},
wantErr: false,
wantObj: &v1alpha1.FeatureFlagConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: "FeatureFlagconfig1",
Namespace: "default",
},
Spec: v1alpha1.FeatureFlagConfigurationSpec{
ServiceProvider: &v1alpha1.FeatureFlagServiceProvider{
Name: "name1",
Credentials: &corev1.ObjectReference{
Kind: "Pod",
Namespace: "default",
Name: "pod1",
},
},
SyncProvider: &v1alpha1.FeatureFlagSyncProvider{
Name: "syncprovider1",
HttpSyncConfiguration: &v1alpha1.HttpSyncConfiguration{
Target: "target1",
BearerToken: "token",
},
},
FlagDSpec: &v1alpha1.FlagDSpec{
Envs: []corev1.EnvVar{
{
Name: "var1",
Value: "val1",
},
{
Name: "var2",
Value: "val2",
},
},
},
FeatureFlagSpec: `{"flags":{"flag1":{"state":"ok","variants":"variant1","defaultVariant":"default"}}}`,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dst := v1alpha1.FeatureFlagConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: v1alpha1.FeatureFlagConfigurationSpec{},
Status: v1alpha1.FeatureFlagConfigurationStatus{},
}
if err := tt.src.ConvertTo(&dst); (err != nil) != tt.wantErr {
t.Errorf("ConvertTo() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantObj != nil {
require.Equal(t, tt.wantObj, &dst, "Object was not converted correctly")
}
})
}
}
func TestFeatureFlagConfiguration_ConvertFrom_Errorcase(t *testing.T) {
// A random different object is used here to simulate a different API version
testObj := v2.ExternalJob{}
dst := &FeatureFlagConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: FeatureFlagConfigurationSpec{},
Status: FeatureFlagConfigurationStatus{},
}
if err := dst.ConvertFrom(&testObj); err == nil {
t.Errorf("ConvertFrom() error = %v", err)
} else {
require.ErrorIs(t, err, common.ErrCannotCastFeatureFlagConfiguration)
}
}
func TestFeatureFlagConfiguration_ConvertTo_Errorcase(t *testing.T) {
testObj := FeatureFlagConfiguration{}
// A random different object is used here to simulate a different API version
dst := v2.ExternalJob{}
if err := testObj.ConvertTo(&dst); err == nil {
t.Errorf("ConvertTo() error = %v", err)
} else {
require.ErrorIs(t, err, common.ErrCannotCastFeatureFlagConfiguration)
}
}

View File

@ -1,80 +0,0 @@
/*
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 v1alpha2
import (
"fmt"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha2/common"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)
func (src *FlagSourceConfiguration) ConvertTo(dstRaw conversion.Hub) error {
dst, ok := dstRaw.(*v1alpha1.FlagSourceConfiguration)
if !ok {
return fmt.Errorf("type %T %w", dstRaw, common.ErrCannotCastFlagSourceConfiguration)
}
// Copy equal stuff to new object
// DO NOT COPY TypeMeta
dst.ObjectMeta = src.ObjectMeta
dst.Spec = v1alpha1.FlagSourceConfigurationSpec{
MetricsPort: src.Spec.MetricsPort,
Port: src.Spec.Port,
SocketPath: src.Spec.SocketPath,
Evaluator: src.Spec.Evaluator,
Image: src.Spec.Image,
Tag: src.Spec.Tag,
Sources: []v1alpha1.Source{},
SyncProviderArgs: src.Spec.SyncProviderArgs,
LogFormat: src.Spec.LogFormat,
DefaultSyncProvider: v1alpha1.SyncProviderType(src.Spec.DefaultSyncProvider),
ProbesEnabled: src.Spec.ProbesEnabled,
DebugLogging: common.FalseVal(),
OtelCollectorUri: src.Spec.OtelCollectorUri,
}
return nil
}
func (dst *FlagSourceConfiguration) ConvertFrom(srcRaw conversion.Hub) error {
src, ok := srcRaw.(*v1alpha1.FlagSourceConfiguration)
if !ok {
return fmt.Errorf("type %T %w", srcRaw, common.ErrCannotCastFlagSourceConfiguration)
}
// Copy equal stuff to new object
// DO NOT COPY TypeMeta
dst.ObjectMeta = src.ObjectMeta
dst.Spec = FlagSourceConfigurationSpec{
MetricsPort: src.Spec.MetricsPort,
Port: src.Spec.Port,
SocketPath: src.Spec.SocketPath,
Evaluator: src.Spec.Evaluator,
Image: src.Spec.Image,
Tag: src.Spec.Tag,
SyncProviderArgs: src.Spec.SyncProviderArgs,
LogFormat: src.Spec.LogFormat,
DefaultSyncProvider: string(src.Spec.DefaultSyncProvider),
ProbesEnabled: src.Spec.ProbesEnabled,
}
return nil
}

View File

@ -1,210 +0,0 @@
package v1alpha2
import (
"testing"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha2/common"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "sigs.k8s.io/controller-runtime/pkg/webhook/conversion/testdata/api/v2"
)
func TestFlagSourceConfiguration_ConvertFrom(t *testing.T) {
tt := true
tests := []struct {
name string
srcObj *v1alpha1.FlagSourceConfiguration
wantErr bool
wantObj *FlagSourceConfiguration
}{
{
name: "Test that conversion from v1alpha1 to v1alpha2 works",
srcObj: &v1alpha1.FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FlagSourceConfiguration",
APIVersion: "core.openfeature.dev/v1alpha1",
},
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: v1alpha1.FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
Sources: []v1alpha1.Source{
{
Source: "source",
Provider: "provider",
HttpSyncBearerToken: "token",
TLS: false,
CertPath: "/tmp/path",
ProviderID: "myapp",
Selector: "source=database",
},
},
EnvVars: []corev1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
DefaultSyncProvider: v1alpha1.SyncProviderType("provider"),
LogFormat: "log",
EnvVarPrefix: "pre",
RolloutOnChange: &tt,
SyncProviderArgs: []string{"provider", "arg"},
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
},
wantErr: false,
wantObj: &FlagSourceConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
SyncProviderArgs: []string{"provider", "arg"},
LogFormat: "log",
DefaultSyncProvider: "provider",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dst := &FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: FlagSourceConfigurationSpec{},
Status: FlagSourceConfigurationStatus{},
}
if err := dst.ConvertFrom(tt.srcObj); (err != nil) != tt.wantErr {
t.Errorf("ConvertFrom() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantObj != nil {
require.Equal(t, tt.wantObj, dst, "Object was not converted correctly")
}
})
}
}
func TestFlagSourceConfiguration_ConvertTo(t *testing.T) {
tests := []struct {
name string
src *FlagSourceConfiguration
wantErr bool
wantObj *v1alpha1.FlagSourceConfiguration
}{
{
name: "Test that conversion from v1alpha2 to v1alpha1 works",
src: &FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FlagSourceConfiguration",
APIVersion: "core.openfeature.dev/v1alpha2",
},
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
DefaultSyncProvider: "provider",
LogFormat: "log",
SyncProviderArgs: []string{"provider", "arg"},
},
},
wantErr: false,
wantObj: &v1alpha1.FlagSourceConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: v1alpha1.FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
Sources: []v1alpha1.Source{},
DefaultSyncProvider: v1alpha1.SyncProviderType("provider"),
LogFormat: "log",
EnvVarPrefix: "",
RolloutOnChange: nil,
SyncProviderArgs: []string{"provider", "arg"},
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dst := v1alpha1.FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: v1alpha1.FlagSourceConfigurationSpec{},
Status: v1alpha1.FlagSourceConfigurationStatus{},
}
if err := tt.src.ConvertTo(&dst); (err != nil) != tt.wantErr {
t.Errorf("ConvertTo() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantObj != nil {
require.Equal(t, tt.wantObj, &dst, "Object was not converted correctly")
}
})
}
}
func TestFlagSourceConfiguration_ConvertFrom_Errorcase(t *testing.T) {
// A random different object is used here to simulate a different API version
testObj := v2.ExternalJob{}
dst := &FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: FlagSourceConfigurationSpec{},
Status: FlagSourceConfigurationStatus{},
}
if err := dst.ConvertFrom(&testObj); err == nil {
t.Errorf("ConvertFrom() error = %v", err)
} else {
require.ErrorIs(t, err, common.ErrCannotCastFlagSourceConfiguration)
}
}
func TestFlagSourceConfiguration_ConvertTo_Errorcase(t *testing.T) {
testObj := FlagSourceConfiguration{}
// A random different object is used here to simulate a different API version
dst := v2.ExternalJob{}
if err := testObj.ConvertTo(&dst); err == nil {
t.Errorf("ConvertTo() error = %v", err)
} else {
require.ErrorIs(t, err, common.ErrCannotCastFlagSourceConfiguration)
}
}

View File

@ -1,15 +0,0 @@
package common
import "errors"
var ErrCannotCastFlagSourceConfiguration = errors.New("cannot cast FlagSourceConfiguration to v1alpha3")
func TrueVal() *bool {
b := true
return &b
}
func FalseVal() *bool {
b := false
return &b
}

View File

@ -1,113 +0,0 @@
/*
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 v1alpha3
import (
"fmt"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha3/common"
"sigs.k8s.io/controller-runtime/pkg/conversion"
)
func (src *FlagSourceConfiguration) ConvertTo(dstRaw conversion.Hub) error {
dst, ok := dstRaw.(*v1alpha1.FlagSourceConfiguration)
if !ok {
return fmt.Errorf("type %T %w", dstRaw, common.ErrCannotCastFlagSourceConfiguration)
}
// Copy equal stuff to new object
// DO NOT COPY TypeMeta
dst.ObjectMeta = src.ObjectMeta
sources := []v1alpha1.Source{}
for _, sp := range src.Spec.Sources {
sources = append(sources, v1alpha1.Source{
Source: sp.Source,
Provider: v1alpha1.SyncProviderType(sp.Provider),
HttpSyncBearerToken: sp.HttpSyncBearerToken,
TLS: sp.TLS,
CertPath: sp.CertPath,
ProviderID: sp.ProviderID,
Selector: sp.Selector,
})
}
dst.Spec = v1alpha1.FlagSourceConfigurationSpec{
MetricsPort: src.Spec.MetricsPort,
Port: src.Spec.Port,
SocketPath: src.Spec.SocketPath,
Evaluator: src.Spec.Evaluator,
Image: src.Spec.Image,
Tag: src.Spec.Tag,
Sources: sources,
EnvVars: src.Spec.EnvVars,
DefaultSyncProvider: v1alpha1.SyncProviderType(src.Spec.DefaultSyncProvider),
LogFormat: src.Spec.LogFormat,
EnvVarPrefix: src.Spec.EnvVarPrefix,
RolloutOnChange: src.Spec.RolloutOnChange,
ProbesEnabled: src.Spec.ProbesEnabled,
DebugLogging: src.Spec.DebugLogging,
OtelCollectorUri: src.Spec.OtelCollectorUri,
}
return nil
}
func (dst *FlagSourceConfiguration) ConvertFrom(srcRaw conversion.Hub) error {
src, ok := srcRaw.(*v1alpha1.FlagSourceConfiguration)
if !ok {
return fmt.Errorf("type %T %w", srcRaw, common.ErrCannotCastFlagSourceConfiguration)
}
// Copy equal stuff to new object
// DO NOT COPY TypeMeta
dst.ObjectMeta = src.ObjectMeta
sources := []Source{}
for _, sp := range src.Spec.Sources {
sources = append(sources, Source{
Source: sp.Source,
Provider: SyncProviderType(sp.Provider),
HttpSyncBearerToken: sp.HttpSyncBearerToken,
TLS: sp.TLS,
CertPath: sp.CertPath,
ProviderID: sp.ProviderID,
Selector: sp.Selector,
})
}
dst.Spec = FlagSourceConfigurationSpec{
MetricsPort: src.Spec.MetricsPort,
Port: src.Spec.Port,
SocketPath: src.Spec.SocketPath,
Evaluator: src.Spec.Evaluator,
Image: src.Spec.Image,
Tag: src.Spec.Tag,
Sources: sources,
EnvVars: src.Spec.EnvVars,
DefaultSyncProvider: string(src.Spec.DefaultSyncProvider),
LogFormat: src.Spec.LogFormat,
EnvVarPrefix: src.Spec.EnvVarPrefix,
RolloutOnChange: src.Spec.RolloutOnChange,
ProbesEnabled: src.Spec.ProbesEnabled,
DebugLogging: src.Spec.DebugLogging,
OtelCollectorUri: src.Spec.OtelCollectorUri,
}
return nil
}

View File

@ -1,275 +0,0 @@
package v1alpha3
import (
"testing"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha1"
"github.com/open-feature/open-feature-operator/apis/core/v1alpha3/common"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v2 "sigs.k8s.io/controller-runtime/pkg/webhook/conversion/testdata/api/v2"
)
func TestFlagSourceConfiguration_ConvertFrom(t *testing.T) {
tt := true
tests := []struct {
name string
srcObj *v1alpha1.FlagSourceConfiguration
wantErr bool
wantObj *FlagSourceConfiguration
}{
{
name: "Test that conversion from v1alpha1 to v1alpha3 works",
srcObj: &v1alpha1.FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FlagSourceConfiguration",
APIVersion: "core.openfeature.dev/v1alpha1",
},
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: v1alpha1.FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
Sources: []v1alpha1.Source{
{
Source: "source",
Provider: "provider",
HttpSyncBearerToken: "token",
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
},
EnvVars: []corev1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
DefaultSyncProvider: v1alpha1.SyncProviderType("provider"),
LogFormat: "log",
EnvVarPrefix: "pre",
RolloutOnChange: &tt,
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
},
wantErr: false,
wantObj: &FlagSourceConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
Sources: []Source{
{
Source: "source",
Provider: "provider",
HttpSyncBearerToken: "token",
TLS: true,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
},
EnvVars: []corev1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
DefaultSyncProvider: "provider",
LogFormat: "log",
EnvVarPrefix: "pre",
RolloutOnChange: &tt,
DebugLogging: common.FalseVal(),
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dst := &FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: FlagSourceConfigurationSpec{},
Status: FlagSourceConfigurationStatus{},
}
if err := dst.ConvertFrom(tt.srcObj); (err != nil) != tt.wantErr {
t.Errorf("ConvertFrom() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantObj != nil {
require.Equal(t, tt.wantObj, dst, "Object was not converted correctly")
}
})
}
}
func TestFlagSourceConfiguration_ConvertTo(t *testing.T) {
tt := true
tests := []struct {
name string
src *FlagSourceConfiguration
wantErr bool
wantObj *v1alpha1.FlagSourceConfiguration
}{
{
name: "Test that conversion from v1alpha3 to v1alpha1 works",
src: &FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{
Kind: "FlagSourceConfiguration",
APIVersion: "core.openfeature.dev/v1alpha3",
},
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
Sources: []Source{
{
Source: "source",
Provider: "provider",
HttpSyncBearerToken: "token",
TLS: false,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
},
EnvVars: []corev1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
DefaultSyncProvider: "provider",
LogFormat: "log",
EnvVarPrefix: "pre",
RolloutOnChange: &tt,
DebugLogging: common.FalseVal(),
},
},
wantErr: false,
wantObj: &v1alpha1.FlagSourceConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: "flagsourceconfig1",
Namespace: "default",
},
Spec: v1alpha1.FlagSourceConfigurationSpec{
MetricsPort: 20,
Port: 21,
SocketPath: "path",
Evaluator: "eval",
Image: "img",
Tag: "tag",
Sources: []v1alpha1.Source{
{
Source: "source",
Provider: "provider",
HttpSyncBearerToken: "token",
TLS: false,
CertPath: "etc/cert.ca",
ProviderID: "app",
Selector: "source=database",
},
},
EnvVars: []corev1.EnvVar{
{
Name: "env1",
Value: "val1",
},
{
Name: "env2",
Value: "val2",
},
},
DefaultSyncProvider: v1alpha1.SyncProviderType("provider"),
LogFormat: "log",
EnvVarPrefix: "pre",
RolloutOnChange: &tt,
DebugLogging: common.FalseVal(),
OtelCollectorUri: "",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
dst := v1alpha1.FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: v1alpha1.FlagSourceConfigurationSpec{},
Status: v1alpha1.FlagSourceConfigurationStatus{},
}
if err := tt.src.ConvertTo(&dst); (err != nil) != tt.wantErr {
t.Errorf("ConvertTo() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantObj != nil {
require.Equal(t, tt.wantObj, &dst, "Object was not converted correctly")
}
})
}
}
func TestFlagSourceConfiguration_ConvertFrom_Errorcase(t *testing.T) {
// A random different object is used here to simulate a different API version
testObj := v2.ExternalJob{}
dst := &FlagSourceConfiguration{
TypeMeta: v1.TypeMeta{},
ObjectMeta: v1.ObjectMeta{},
Spec: FlagSourceConfigurationSpec{},
Status: FlagSourceConfigurationStatus{},
}
if err := dst.ConvertFrom(&testObj); err == nil {
t.Errorf("ConvertFrom() error = %v", err)
} else {
require.ErrorIs(t, err, common.ErrCannotCastFlagSourceConfiguration)
}
}
func TestFlagSourceConfiguration_ConvertTo_Errorcase(t *testing.T) {
testObj := FlagSourceConfiguration{}
// A random different object is used here to simulate a different API version
dst := v2.ExternalJob{}
if err := testObj.ConvertTo(&dst); err == nil {
t.Errorf("ConvertTo() error = %v", err)
} else {
require.ErrorIs(t, err, common.ErrCannotCastFlagSourceConfiguration)
}
}

View File

@ -1,11 +0,0 @@
package v1beta1
type SyncProviderType string
const (
SyncProviderKubernetes SyncProviderType = "kubernetes"
SyncProviderFilepath SyncProviderType = "file"
SyncProviderHttp SyncProviderType = "http"
SyncProviderGrpc SyncProviderType = "grpc"
SyncProviderFlagdProxy SyncProviderType = "flagd-proxy"
)

View File

@ -1,24 +0,0 @@
package v1beta1
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())
}

View File

@ -1,66 +0,0 @@
module github.com/open-feature/open-feature-operator/apis
go 1.19
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/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2 // 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.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
golang.org/x/time v0.3.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // 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/apiextensions-apiserver v0.26.1 // indirect
k8s.io/client-go v0.26.1 // indirect
k8s.io/component-base v0.26.1 // indirect
k8s.io/klog/v2 v2.80.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // 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
sigs.k8s.io/yaml v1.3.0 // indirect
)

View File

@ -1,602 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
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/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
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/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
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/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2 h1:hAHbPm5IJGijwng3PWk09JkG9WeqChjprR5s9bBZ+OM=
github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
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/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/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-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/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.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
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=
gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/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.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.26.4 h1:qSG2PmtcD23BkYiWfoYAcak870eF/hE7NNYBYavTT94=
k8s.io/api v0.26.4/go.mod h1:WwKEXU3R1rgCZ77AYa7DFksd9/BAIKyOmRlbVxgvjCk=
k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI=
k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM=
k8s.io/apimachinery v0.26.4 h1:rZccKdBLg9vP6J09JD+z8Yr99Ce8gk3Lbi9TCx05Jzs=
k8s.io/apimachinery v0.26.4/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU=
k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE=
k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4=
k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU=
k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4=
k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
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.2.36" # 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.2.36" # 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

@ -45,6 +45,13 @@ helm repo update
helm upgrade --install open-feature-operator openfeature/open-feature-operator
```
> [!NOTE]
> If you upgrade to OFO `v0.5.4` or higher while using a `flagd-proxy` provider, the instance of
`flagd-proxy` will be automatically upgraded to the latest supported version by the `open-feature-operator`.
The upgrade of `flagd-proxy` will also consider your current `FeatureFlagSource` configuration and adapt
the `flagd-proxy` Deployment accordingly.
If you are upgrading OFO to `v0.5.3` or lower, `flagd-proxy` (if present) won't be upgraded automatically.
#### Upgrade CRDs
CRDs are not upgraded automatically with helm (https://helm.sh/docs/chart_best_practices/custom_resource_definitions/).
@ -54,16 +61,16 @@ OpenFeature Operator's CRDs are templated, and can be updated apart from the ope
helm template openfeature/open-feature-operator -s templates/{CRD} | kubectl apply -f -
```
For the `featureflagconfigurations.core.openfeature.dev` CRD:
For the `featureflags.core.openfeature.dev` CRD:
```sh
helm template openfeature/open-feature-operator -s templates/apiextensions.k8s.io_v1_customresourcedefinition_featureflagconfigurations.core.openfeature.dev.yaml | kubectl apply -f -
helm template openfeature/open-feature-operator -s templates/apiextensions.k8s.io_v1_customresourcedefinition_featureflags.core.openfeature.dev.yaml | kubectl apply -f -
```
For the `flagsourceconfigurations.core.openfeature.dev` CRD:
For the `featureflagsources.core.openfeature.dev` CRD:
```sh
helm template openfeature/open-feature-operator -s templates/apiextensions.k8s.io_v1_customresourcedefinition_flagsourceconfigurations.core.openfeature.dev.yaml | kubectl apply -f -
helm template openfeature/open-feature-operator -s templates/apiextensions.k8s.io_v1_customresourcedefinition_featureflagsources.core.openfeature.dev.yaml | kubectl apply -f -
```
Keep in mind, you can set values as usual during this process:
@ -90,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.metricsPort` | Sets the value of the `XXX_METRICS_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.6.3` |
| `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`, `filepath` 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.metricsPort` | Sets the port to expose the metrics API on. | `8016` |
| `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.2.8` |
| `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.2.36` |
| `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,13 +2,34 @@
## @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.
port: 8013
## @param sidecarConfiguration.metricsPort Sets the value of the `XXX_METRICS_PORT` environment variable for the injected sidecar.
metricsPort: 8014
## @param sidecarConfiguration.managementPort Sets the value of the `XXX_MANAGEMENT_PORT` environment variable for the injected sidecar.
managementPort: 8014
## @param sidecarConfiguration.socketPath Sets the value of the `XXX_SOCKET_PATH` environment variable for the injected sidecar.
socketPath: ""
image:
@ -16,12 +37,12 @@ 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.6.3
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.
envVarPrefix: "FLAGD"
## @param 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`, `filepath` and `http`.
## @param 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`.
defaultSyncProvider: kubernetes
## @param sidecarConfiguration.evaluator Sets the value of the `XXX_EVALUATOR` environment variable for the injected sidecar container.
evaluator: json
@ -33,48 +54,82 @@ 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.metricsPort Sets the port to expose the metrics API on.
metricsPort: 8016
## @param flagdProxyConfiguration.managementPort Sets the port to expose the management API on.
managementPort: 8016
image:
## @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.2.8
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.2.36 # 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

@ -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
@ -13,7 +12,7 @@ spec:
listKind: FeatureFlagConfigurationList
plural: featureflagconfigurations
shortNames:
- ff
- ffc
singular: featureflagconfiguration
scope: Namespaced
versions:
@ -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
@ -13,7 +12,7 @@ spec:
listKind: FeatureFlagList
plural: featureflags
shortNames:
- ffc
- ff
singular: featureflag
scope: Namespaced
versions:
@ -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 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 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,19 +174,18 @@ spec:
type: object
type: array
evaluator:
default: json
description: Evaluator sets an evaluator, defaults to 'json'
type: string
image:
description: Image allows for the sidecar image to be overridden,
defaults to 'ghcr.io/open-feature/flagd'
type: string
logFormat:
default: json
description: LogFormat allows for the sidecar log format to be overridden,
defaults to 'json'
type: string
metricsPort:
description: MetricsPort defines the port to serve metrics on, defaults
to 8014
managementPort:
default: 8014
description: ManagemetPort defines the port to serve management on,
defaults to 8014
format: int32
type: integer
otelCollectorUri:
@ -180,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
@ -192,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
@ -219,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:
@ -229,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
@ -256,9 +282,14 @@ 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
filepath
file
type: string
providerID:
description: ProviderID is an identifier to be used in grpc
@ -286,10 +317,6 @@ spec:
items:
type: string
type: array
tag:
description: Tag to be appended to the sidecar image, defaults to
'main'
type: string
required:
- sources
type: object

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

@ -2,29 +2,21 @@
# since it depends on service name and namespace that are out of this kustomize package.
# It should be run by config/default
resources:
- bases/core.openfeature.dev_featureflagconfigurations.yaml
- bases/core.openfeature.dev_flagsourceconfigurations.yaml
- 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_featureflagconfigurations.yaml
- patches/webhook_in_flagsourceconfigurations.yaml
#- 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_featureflagconfigurations.yaml
- patches/cainjection_in_flagsourceconfigurations.yaml
#- 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

@ -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: flagsourceconfigurations.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: featureflagconfigurations.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: flagsourceconfigurations.core.openfeature.dev

View File

@ -2,7 +2,7 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: featureflags.core.openfeature.dev
name: flagds.core.openfeature.dev
spec:
conversion:
strategy: Webhook

View File

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

View File

@ -2,7 +2,7 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: featureflagsources.core.openfeature.dev
name: inprocessconfigurations.core.openfeature.dev
spec:
conversion:
strategy: Webhook

View File

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

View File

@ -1,16 +0,0 @@
# The following patch enables a conversion webhook for the CRD
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: flagsourceconfigurations.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

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