The Kubernetes facade
Everything starts at the Kubernetes facade (RoundlyConsulting\KubernetesApi\Facades\Kubernetes). It hands out clusters — immutable clients — and, through them, resource objects (Pod, Deployment, …) that read and write the apiserver. Calls without a cluster name go to the default cluster from config/kubernetes.php:
use RoundlyConsulting\KubernetesApi\Facades\Kubernetes;
Kubernetes::pods()->get(); // default cluster, default namespace
Kubernetes::namespace('shop')->deployments()->get(); // default cluster, scoped to shop
Kubernetes::cluster('production')->services()->get(); // a named cluster
Kubernetes::ping(); // bool — does the apiserver answer?
Kubernetes::version()->gitVersion; // "v1.34.0" (a VersionInfo DTO)
Kubernetes::hasCluster('production'); // bool
Kubernetes::clusters(); // ['default', 'production']
Kubernetes::url('https://127.0.0.1:6443')->withToken($token); // a new, blank ad-hoc cluster
Kubernetes::fromKubeConfig(context: 'staging'); // a new cluster from a kubeconfig contextMethod reference
| Method | Returns | What it does |
|---|---|---|
cluster(?string $name = null) | Cluster | A configured or registered cluster — the default one when null. Resolved once and reused. |
hasCluster(string $name) · clusters() | bool · list<string> | Whether a cluster exists; every configured and registered name. |
registerCluster(string $name, Closure $definition) | void | Define a cluster in code; overrides a configured one of the same name. |
registerResource(string $name, string $class) | void | Register a resource class under an accessor name for every cluster. |
namespace(string $namespace) | Cluster | The default cluster, scoped to one namespace. |
ping() · version() | bool · VersionInfo | Health and build information of the default cluster. |
url(string $url) | Cluster | A new, blank ad-hoc cluster. |
connect(KubeConfig $config) | Cluster | A new ad-hoc cluster from a resolved connection. |
fromKubeConfig(?string $path, ?string $context) · inCluster() | Cluster | A new ad-hoc cluster from a kubeconfig context or the pod’s service account. |
resource(string $class) | Resource | Any resource class, bound to the default cluster. |
pods(), deployments(), services(), … (33 accessors) | the resource | Every packaged resource, bound to the default cluster. |
apps(), tenantNamespace(), … | resource / macro result | A custom resource registered under that name, or a Cluster macro — on the default cluster. |
fake() | KubernetesFake | Swap in the in-memory apiserver for tests — see Testing. |
The Cluster handle
cluster(), namespace(), url(), connect(), fromKubeConfig() and inCluster() all return a RoundlyConsulting\KubernetesApi\Cluster. Every Cluster has the same 33 accessors as the facade, plus its own identity, health checks and a raw request() escape hatch that is authenticated, rate limited and faked like everything else:
$cluster = Kubernetes::cluster('production');
$cluster->name(); // 'production' (null for ad-hoc clusters)
$cluster->defaultNamespace(); // from clusters.production.namespace
$cluster->hasResource('apps'); // is an accessor registered under that name?
$cluster->getUrl(); // plus getToken(), getManagerName(), shouldVerify()…
// Raw escape hatch — authenticated, rate limited and faked like the typed resources
$response = $cluster->request('GET', '/apis/apps/v1/namespaces/shop/deployments', ['limit' => 10]);
$response->json('items');| Cluster method | Returns | Notes |
|---|---|---|
name() | ?string | The registration name; null for ad-hoc clusters (url(), connect(), fromKubeConfig(), inCluster()). |
url() · with…() · without…() · withManagerName() · withDefaultNamespace() | a copy | Connection and credentials — see Connecting to a cluster. |
namespace(string) · namespaceScope() | Cluster · ?string | A copy scoped to one namespace; the scope, if any. |
defaultNamespace() | string | The soft default for namespaced resources. |
applyConfig(KubeConfig) | a copy | Replaces URL, token, certificate, key, CA and verification. |
resource(class-string) · hasResource(string) | Resource · bool | Any resource class bound to this cluster; whether an accessor name is registered. |
ping() · version() | bool · VersionInfo | ping() is false on an apiserver error, a connection failure or a missing URL; a rate-limit exhaustion still throws. |
request($method, $path, $query = [], $body = '', $contentType = null, $stream = false) | Response | Raw escape hatch through the cluster’s transport; a failed response throws KubernetesException. |
getUrl() · getToken() · getManagerName() · shouldVerify() · getPathTo…() | readers | The credentials the cluster carries. |
- Clusters are immutable: every with…() / without…() call, url(), withManagerName(), withDefaultNamespace() and namespace() return a new cluster, so a client handed out by the facade can never be re-pointed or re-credentialed by another caller.
- Named clusters are resolved once and reused; url(), connect(), fromKubeConfig() and inCluster() build a new ad-hoc cluster on every call.
- Cluster::execute() is @internal — it opens the exec WebSocket for Pod::exec(); call exec() on a pod instead.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.