Skip to content

Commit 2ba37a4

Browse files
authored
Merge pull request #275 from finos/feat/add-k8s-provider
feat(k8s): native Kubernetes provider with Pod, Deployment, StatefulSet, and Job handlers
2 parents 96a6a30 + a835a2b commit 2ba37a4

288 files changed

Lines changed: 47907 additions & 934 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ jobs:
9898
# Per-provider matrix. One job per provider subtree under
9999
# tests/providers/. New providers land here as new matrix entries —
100100
# no separate onmoto job needed (moto-mocked tests live under
101-
# tests/providers/aws/moto and run as part of the aws entry).
101+
# tests/providers/aws/mocked and run as part of the aws entry).
102102
providers-tests:
103103
name: Providers Tests
104104
needs: [config, setup-cache]

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
3535
- New `[aws]` extra (alias for AWS deps currently in core). The canonical install
3636
command going forward is `pip install orb-py[aws]`. This continues to work
3737
unchanged when AWS deps move out of core in a future major version.
38+
- New `[k8s]` extra: modern first-class Kubernetes provider with Pod, Deployment, StatefulSet, and Job handlers, watch-based ingestion, startup reconciliation, and orphan garbage collection. Install with `pip install "orb-py[k8s]"`. See `docs/root/providers/kubernetes/index.md` for the full reference.
3839
- New `[all-providers]` meta-extra: pulls in all currently implemented providers.
3940
- New `[monitoring-aws]` extra: AWS-specific OpenTelemetry boto instrumentation (previously bundled inside `[monitoring]`).
4041
- New `[test-aws]` extra: moto + response-mocking deps for AWS test suites.
4142
- Architecture test `test_boto3_leak_detection.py`: asserts boto3/botocore are never imported outside `providers/aws/` except by guarded backward-compat shims.
4243
- Unit tests `test_no_provider_install.py`: verifies ORB core modules boot cleanly when AWS deps are absent.
44+
- Third-party provider plugin discovery via the `orb.providers` entry-point group. Plugins are loaded by `discover_provider_plugins()` after the built-in providers register; failures are logged and tolerated so a broken plugin cannot prevent ORB from starting. See `docs/root/providers/kubernetes/plugin-authoring.md` for the plugin contract and a worked Kubeflow MPIJob example.
45+
- `KubernetesProviderStrategy.register_handler` classmethod: plugin extension point for attaching a new `provider_api` handler to the Kubernetes provider without forking the strategy.
46+
- Kubernetes provider documentation under `docs/root/providers/kubernetes/`: overview, configuration reference, handlers guide, authentication guide, RBAC example, migration guide from `orb.k8s_legacy`, and plugin-authoring walkthrough.
4347

4448
### Changed
4549

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# Include all modular makefiles
77
include makefiles/common.mk
88
include makefiles/dev.mk
9+
include makefiles/providers.mk
910
include makefiles/quality.mk
1011
include makefiles/ci.mk
1112
include makefiles/deploy.mk

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ Built for AWS today (EC2, Auto Scaling Groups, SpotFleet, EC2Fleet), with an ext
3636

3737
**Provider support:**
3838
- **AWS** — EC2 RunInstances, EC2Fleet, SpotFleet, Auto Scaling Groups
39-
- **Custom** — extensible via [provider registry](docs/root/developer_guide/architecture.md)
39+
- **Kubernetes** — Pod, Deployment, StatefulSet, Job (`pip install "orb-py[k8s]"`; see [Kubernetes provider docs](docs/root/providers/k8s/index.md))
40+
- **Custom** — extensible via [provider registry](docs/root/developer_guide/architecture.md) and the [`orb.providers` entry-point group](docs/root/providers/k8s/plugin-authoring.md)
4041

4142
**Scheduler support:**
4243
- **HostFactory** — runs as an [IBM Spectrum Symphony provider plugin](#hostfactory-integration)
@@ -96,6 +97,7 @@ will return a clear "no provider configured" error rather than an ImportError.
9697

9798
```bash
9899
pip install "orb-py[aws]" # AWS provider (boto3 + botocore)
100+
pip install "orb-py[k8s]" # Kubernetes provider (kubernetes SDK)
99101
pip install "orb-py[aws,cli]" # AWS provider + colored CLI output
100102
pip install "orb-py[aws,api]" # AWS provider + REST API server
101103
pip install "orb-py[monitoring-aws]" # AWS provider + full monitoring stack
@@ -108,6 +110,8 @@ pip install "orb-py[all]" # All providers + all features
108110
|----------|----------------|
109111
| Core only (no provider) | `pip install orb-py` |
110112
| AWS operator | `pip install "orb-py[aws]"` |
113+
| Kubernetes operator | `pip install "orb-py[k8s]"` |
114+
| AWS + Kubernetes | `pip install "orb-py[aws,k8s]"` |
111115
| AWS + colored CLI | `pip install "orb-py[aws,cli]"` |
112116
| AWS + REST API | `pip install "orb-py[aws,api]"` |
113117
| AWS + monitoring | `pip install "orb-py[monitoring-aws]"` |

config/aws_templates.json

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"name": "EC2 Fleet Instant On-Demand",
1919
"providerApi": "EC2Fleet",
2020
"providerType": "aws",
21-
"createdAt": "2026-06-24T12:58:15.944146"
21+
"createdAt": "2026-07-06T22:07:11.806716"
2222
},
2323
{
2424
"templateId": "EC2Fleet-Instant-Spot",
@@ -38,7 +38,7 @@
3838
"name": "EC2 Fleet Instant Spot",
3939
"providerApi": "EC2Fleet",
4040
"providerType": "aws",
41-
"createdAt": "2026-06-24T12:58:15.944377"
41+
"createdAt": "2026-07-06T22:07:11.806807"
4242
},
4343
{
4444
"templateId": "EC2Fleet-Instant-Mixed",
@@ -58,7 +58,7 @@
5858
"name": "EC2 Fleet Instant Mixed",
5959
"providerApi": "EC2Fleet",
6060
"providerType": "aws",
61-
"createdAt": "2026-06-24T12:58:15.944400",
61+
"createdAt": "2026-07-06T22:07:11.806823",
6262
"percentOnDemand": 30
6363
},
6464
{
@@ -78,7 +78,7 @@
7878
"name": "EC2 Fleet Request On-Demand",
7979
"providerApi": "EC2Fleet",
8080
"providerType": "aws",
81-
"createdAt": "2026-06-24T12:58:15.944411"
81+
"createdAt": "2026-07-06T22:07:11.806831"
8282
},
8383
{
8484
"templateId": "EC2Fleet-Request-Spot",
@@ -98,7 +98,7 @@
9898
"name": "EC2 Fleet Request Spot",
9999
"providerApi": "EC2Fleet",
100100
"providerType": "aws",
101-
"createdAt": "2026-06-24T12:58:15.944421"
101+
"createdAt": "2026-07-06T22:07:11.806839"
102102
},
103103
{
104104
"templateId": "EC2Fleet-Request-Mixed",
@@ -119,7 +119,7 @@
119119
"name": "EC2 Fleet Request Mixed",
120120
"providerApi": "EC2Fleet",
121121
"providerType": "aws",
122-
"createdAt": "2026-06-24T12:58:15.944431",
122+
"createdAt": "2026-07-06T22:07:11.806849",
123123
"percentOnDemand": 40,
124124
"allocationStrategyOnDemand": "lowestPrice"
125125
},
@@ -140,7 +140,7 @@
140140
"name": "EC2 Fleet Maintain On-Demand",
141141
"providerApi": "EC2Fleet",
142142
"providerType": "aws",
143-
"createdAt": "2026-06-24T12:58:15.944439"
143+
"createdAt": "2026-07-06T22:07:11.806857"
144144
},
145145
{
146146
"templateId": "EC2Fleet-Maintain-Spot",
@@ -160,7 +160,7 @@
160160
"name": "EC2 Fleet Maintain Spot",
161161
"providerApi": "EC2Fleet",
162162
"providerType": "aws",
163-
"createdAt": "2026-06-24T12:58:15.944454"
163+
"createdAt": "2026-07-06T22:07:11.806864"
164164
},
165165
{
166166
"templateId": "EC2Fleet-Maintain-Mixed",
@@ -181,7 +181,7 @@
181181
"name": "EC2 Fleet Maintain Mixed",
182182
"providerApi": "EC2Fleet",
183183
"providerType": "aws",
184-
"createdAt": "2026-06-24T12:58:15.944463",
184+
"createdAt": "2026-07-06T22:07:11.806870",
185185
"percentOnDemand": 50,
186186
"allocationStrategyOnDemand": "prioritized"
187187
},
@@ -204,7 +204,7 @@
204204
"name": "Spot Fleet Request - Lowest Price",
205205
"providerApi": "SpotFleet",
206206
"providerType": "aws",
207-
"createdAt": "2026-06-24T12:58:15.944477"
207+
"createdAt": "2026-07-06T22:07:11.806881"
208208
},
209209
{
210210
"templateId": "SpotFleet-Request-Diversified",
@@ -225,7 +225,7 @@
225225
"name": "Spot Fleet Request - Diversified",
226226
"providerApi": "SpotFleet",
227227
"providerType": "aws",
228-
"createdAt": "2026-06-24T12:58:15.944484"
228+
"createdAt": "2026-07-06T22:07:11.806887"
229229
},
230230
{
231231
"templateId": "SpotFleet-Request-CapacityOptimized",
@@ -246,7 +246,7 @@
246246
"name": "Spot Fleet Request - Capacity Optimized",
247247
"providerApi": "SpotFleet",
248248
"providerType": "aws",
249-
"createdAt": "2026-06-24T12:58:15.944490"
249+
"createdAt": "2026-07-06T22:07:11.806894"
250250
},
251251
{
252252
"templateId": "SpotFleet-Maintain-LowestPrice",
@@ -267,7 +267,7 @@
267267
"name": "Spot Fleet Maintain - Lowest Price",
268268
"providerApi": "SpotFleet",
269269
"providerType": "aws",
270-
"createdAt": "2026-06-24T12:58:15.944496"
270+
"createdAt": "2026-07-06T22:07:11.806899"
271271
},
272272
{
273273
"templateId": "SpotFleet-Maintain-Diversified",
@@ -288,7 +288,7 @@
288288
"name": "Spot Fleet Maintain - Diversified",
289289
"providerApi": "SpotFleet",
290290
"providerType": "aws",
291-
"createdAt": "2026-06-24T12:58:15.944502"
291+
"createdAt": "2026-07-06T22:07:11.806905"
292292
},
293293
{
294294
"templateId": "SpotFleet-Maintain-CapacityOptimized",
@@ -309,7 +309,7 @@
309309
"name": "Spot Fleet Maintain - Capacity Optimized",
310310
"providerApi": "SpotFleet",
311311
"providerType": "aws",
312-
"createdAt": "2026-06-24T12:58:15.944508"
312+
"createdAt": "2026-07-06T22:07:11.806910"
313313
},
314314
{
315315
"templateId": "ASG-OnDemand",
@@ -327,7 +327,7 @@
327327
"name": "Auto Scaling Group On-Demand",
328328
"providerApi": "ASG",
329329
"providerType": "aws",
330-
"createdAt": "2026-06-24T12:58:15.944518"
330+
"createdAt": "2026-07-06T22:07:11.806920"
331331
},
332332
{
333333
"templateId": "ASG-Spot",
@@ -346,7 +346,7 @@
346346
"name": "Auto Scaling Group Spot",
347347
"providerApi": "ASG",
348348
"providerType": "aws",
349-
"createdAt": "2026-06-24T12:58:15.944532"
349+
"createdAt": "2026-07-06T22:07:11.806929"
350350
},
351351
{
352352
"templateId": "ASG-Mixed",
@@ -365,7 +365,7 @@
365365
"name": "Auto Scaling Group Mixed",
366366
"providerApi": "ASG",
367367
"providerType": "aws",
368-
"createdAt": "2026-06-24T12:58:15.944541",
368+
"createdAt": "2026-07-06T22:07:11.806937",
369369
"percentOnDemand": 30
370370
},
371371
{
@@ -383,7 +383,7 @@
383383
"name": "Run Instances On-Demand",
384384
"providerApi": "RunInstances",
385385
"providerType": "aws",
386-
"createdAt": "2026-06-24T12:58:15.944549"
386+
"createdAt": "2026-07-06T22:07:11.806944"
387387
},
388388
{
389389
"templateId": "RunInstances-Spot",
@@ -401,7 +401,7 @@
401401
"name": "Run Instances Spot",
402402
"providerApi": "RunInstances",
403403
"providerType": "aws",
404-
"createdAt": "2026-06-24T12:58:15.944556"
404+
"createdAt": "2026-07-06T22:07:11.806955"
405405
}
406406
]
407407
}

config/k8s_templates.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"scheduler_type": "hostfactory",
3+
"templates": [
4+
{
5+
"templateId": "k8s-pod-example",
6+
"maxNumber": 1,
7+
"imageId": "busybox:latest",
8+
"priceType": "ondemand",
9+
"allocationStrategy": "lowestPrice",
10+
"name": "Kubernetes Pod example",
11+
"providerApi": "Pod",
12+
"providerType": "k8s",
13+
"createdAt": "2026-07-06T22:07:11.808371"
14+
},
15+
{
16+
"templateId": "k8s-deployment-example",
17+
"maxNumber": 3,
18+
"imageId": "busybox:latest",
19+
"priceType": "ondemand",
20+
"allocationStrategy": "lowestPrice",
21+
"name": "Kubernetes Deployment example",
22+
"providerApi": "Deployment",
23+
"providerType": "k8s",
24+
"createdAt": "2026-07-06T22:07:11.808407"
25+
},
26+
{
27+
"templateId": "k8s-statefulset-example",
28+
"maxNumber": 3,
29+
"imageId": "busybox:latest",
30+
"priceType": "ondemand",
31+
"allocationStrategy": "lowestPrice",
32+
"name": "Kubernetes StatefulSet example",
33+
"providerApi": "StatefulSet",
34+
"providerType": "k8s",
35+
"createdAt": "2026-07-06T22:07:11.808466"
36+
},
37+
{
38+
"templateId": "k8s-job-example",
39+
"maxNumber": 3,
40+
"imageId": "busybox:latest",
41+
"priceType": "ondemand",
42+
"allocationStrategy": "lowestPrice",
43+
"name": "Kubernetes Job example",
44+
"providerApi": "Job",
45+
"providerType": "k8s",
46+
"createdAt": "2026-07-06T22:07:11.808487"
47+
}
48+
]
49+
}

docs/mkdocs.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ nav:
164164
- Feature Mapping: hostfactory/feature_mapping.md
165165
- Deployment Scenarios: hostfactory/deployment_scenarios.md
166166
- Supported APIs: hostfactory/supported-apis.md
167+
- Providers:
168+
- Kubernetes:
169+
- Overview: providers/k8s/index.md
170+
- Infrastructure Discovery: providers/k8s/discovery.md
171+
- Configuration: providers/k8s/configuration.md
172+
- Handlers: providers/k8s/handlers.md
173+
- Authentication: providers/k8s/auth.md
174+
- Migrating from k8s-legacy: providers/k8s/migrating-from-k8s-legacy.md
175+
- Plugin Authoring: providers/k8s/plugin-authoring.md
167176
- CLI Reference:
168177
- Overview: cli/README.md
169178
- Full CLI Reference: cli/cli-reference.md

docs/root/developer_guide/adding_a_provider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ def pytest_collection_modifyitems(config, items):
570570
The AWS provider tests are the reference layout:
571571

572572
- Unit tests: `tests/providers/aws/unit/`
573-
- Mocked integration tests: `tests/providers/aws/moto/`
573+
- Mocked integration tests: `tests/providers/aws/mocked/`
574574
- Real-AWS tests: `tests/providers/aws/live/`
575575
- Contract tests: `tests/providers/aws/contract/`
576576

0 commit comments

Comments
 (0)