---
title: "Custom resources & macros — Kubernetes API for Laravel | Roundly"
description: "Register your own CRDs, swap a built-in resource for your subclass, and extend the client and resources with macros and conditionals."
url: https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel/extending
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Kubernetes API for Laravel](https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel.md)

# Custom resources & macros

Define a resource class for any kind — including your own CRDs — and register it in config/kubernetes.php or at runtime:

```php
use RoundlyConsulting\KubernetesApi\Facades\Kubernetes;
use RoundlyConsulting\KubernetesApi\Resources\Resource;

class Application extends Resource
{
    protected string $version = 'example.com/v2';

    protected string $kind = 'Application';

    protected bool $usesNamespaces = true;
}

Kubernetes::registerResource('apps', Application::class);

Kubernetes::cluster('production')->apps()->get(); // all Application resources
Kubernetes::apps()->get();                        // on the default cluster
```

- $version — the apiVersion. v1 (the default) maps to /api/v1; anything else to /apis/<version>.
- $kind — the kind written into every payload.
- $usesNamespaces — true for namespaced kinds; the default false makes the resource cluster-scoped.
- $plural — the REST plural. Left null it is the lower-cased kind, pluralised; set it when the CRD’s spec.names.plural differs.
- Add the traits you need — HasSpec, HasStatus, HasStatusPhase, HasReplicas… from RoundlyConsulting\\KubernetesApi\\Traits\\Resource.
- A generic Resource set up at runtime with setKind(), setVersion(), setPlural() or usingNamespaces() hands those settings on to what it returns — listed items (which carry no kind or apiVersion), watch events and the results of find(), create(), update(), patch() and delete() — so they can be written back. A payload’s own kind and apiVersion win.

```php
namespace App\Kubernetes;

use RoundlyConsulting\KubernetesApi\Facades\Kubernetes;
use RoundlyConsulting\KubernetesApi\Resources\Resource;
use RoundlyConsulting\KubernetesApi\Traits\Resource\HasSpec;
use RoundlyConsulting\KubernetesApi\Traits\Resource\HasStatus;

class DatabaseMigration extends Resource
{
    use HasSpec;
    use HasStatus;

    protected string $version = 'ops.example.com/v1';

    protected string $kind = 'DatabaseMigration';

    protected ?string $plural = 'dbmigrations';   // the CRD's spec.names.plural

    protected bool $usesNamespaces = true;
}

// Registered or not, any class resolves through resource():
Kubernetes::cluster('production')->resource(DatabaseMigration::class)
    ->setNamespace('shop')
    ->setName('add-orders-index')
    ->setSpec('database', 'orders')
    ->create();
```

## Registering and swapping in config

The resources map is read at call time, and Kubernetes::registerResource() writes into the same map. Pointing a built-in name at your own subclass swaps it on every cluster, the facade included — resource classes are deliberately not final. A name a Cluster method already answers (url, namespace, …) is refused with InvalidResourceException:

```php
// config/kubernetes.php
'resources' => [
    // …keep the built-in entries from the published file…
    'dbMigrations' => App\Kubernetes\DatabaseMigration::class,

    // Swap a built-in: every $cluster->pods() now returns your subclass
    'pods' => App\Kubernetes\Pod::class,
],
```

```php
namespace App\Kubernetes;

use RoundlyConsulting\KubernetesApi\Resources\Pod as BasePod;

class Pod extends BasePod
{
    public function isServing(): bool
    {
        return $this->isRunning() && $this->containersReady();
    }
}
```

## Macros and conditionals

Both Cluster and every resource use Laravel’s Macroable and Conditionable traits, so you can extend and branch fluently. A Cluster macro is also callable on the facade, for the default cluster:

```php
use RoundlyConsulting\KubernetesApi\Cluster;
use RoundlyConsulting\KubernetesApi\Facades\Kubernetes;
use RoundlyConsulting\KubernetesApi\Resources\Deployment;

// A resource macro — $this is the resource
Deployment::macro('isFullyAvailable', function (): bool {
    /** @var Deployment $this */
    return $this->getAvailableReplicasCount() >= $this->getReplicas();
});

// A client macro — $this is the cluster client
Cluster::macro('tenantNamespace', function (string $tenant) {
    /** @var Cluster $this */
    return $this->namespaces()->setName("tenant-{$tenant}");
});

$cluster = Kubernetes::cluster('production');

$cluster->deployments()->setNamespace('shop')->withName('checkout')->find()->isFullyAvailable();
$cluster->tenantNamespace('acme')->create();
Kubernetes::tenantNamespace('acme');   // a Cluster macro also works on the facade (default cluster)

// Conditionable — branch without breaking the chain
$cluster->deployments()->setNamespace('shop')->withName('checkout')->find()
    ->when($peakTraffic, fn (Deployment $deployment) => $deployment->setReplicas(12))
    ->unless($peakTraffic, fn (Deployment $deployment) => $deployment->setReplicas(3))
    ->update();
```

Resource macros whose names start with set, get, with, addTo or remove are intercepted by the magic attribute accessors — pick another prefix, such as is…, has… or find….

## 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 crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel.md)
