---
title: "Patch, scale, rollout & dry-run — Kubernetes API for Laravel | Roundly"
description: "Four patch strategies, scaling through the /scale subresource, kubectl-style rollout restarts and server-validated dry runs."
url: https://roundly-consulting.com/open-source/docs/kubernetes-api-for-laravel/patching
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)

# Patch, scale, rollout & dry-run

patch() sends a targeted change with the Content-Type of the chosen strategy and returns the updated resource — no read-modify-write:

```php
use RoundlyConsulting\KubernetesApi\DataTransferObjects\KubernetesPatch;

// Strategic merge patch
$cluster->deployments()->setNamespace('shop')->withName('checkout')
    ->patch(KubernetesPatch::strategicMerge(['spec' => ['replicas' => 4]]));

// JSON merge patch
$cluster->deployments()->setNamespace('shop')->withName('checkout')
    ->patch(KubernetesPatch::merge(['spec' => ['paused' => true]]));

// JSON Patch — a list of operations
$cluster->deployments()->setNamespace('shop')->withName('checkout')
    ->patch(KubernetesPatch::json([
        ['op' => 'replace', 'path' => '/spec/replicas', 'value' => 6],
        ['op' => 'add', 'path' => '/metadata/labels/release', 'value' => 'v1.4.0'],
    ]));
```

## Server-side apply

KubernetesPatch::apply() sends the body as JSON under the application/apply-patch+yaml content type (JSON is valid YAML). Every write carries your manager name as fieldManager; a server-side apply without one uses kubernetes-api-for-laravel. force: true sends force=true — only ever on a server-side apply — to take over fields another manager owns instead of failing with a 409 conflict:

```php
use RoundlyConsulting\KubernetesApi\DataTransferObjects\KubernetesPatch;

// Server-side apply: sent with your manager name as fieldManager. force: true takes over
// fields another manager owns instead of failing with a 409 conflict.
$cluster->deployments()->setNamespace('shop')->withName('checkout')->patch(
    KubernetesPatch::apply([
        'apiVersion' => 'apps/v1',
        'kind' => 'Deployment',
        'metadata' => ['name' => 'checkout', 'namespace' => 'shop'],
        'spec' => ['replicas' => 4],
    ], force: true),
);

// A fieldManager in the query array wins over the manager name.
$cluster->deployments()->setNamespace('shop')->withName('checkout')->patch(
    KubernetesPatch::apply(['apiVersion' => 'apps/v1', 'kind' => 'Deployment', 'metadata' => ['name' => 'checkout']]),
    ['fieldManager' => 'shop-app'],
);
```

## Patch types

Each strategy is a PatchType case whose backing value is its Content-Type. The enum carries the shared enum helpers from enums-for-laravel — handy when the strategy comes from user input:

```php
use RoundlyConsulting\KubernetesApi\DataTransferObjects\KubernetesPatch;
use RoundlyConsulting\KubernetesApi\Enums\PatchType;

PatchType::StrategicMerge->contentType(); // 'application/strategic-merge-patch+json'
PatchType::StrategicMerge->label();       // 'Strategic Merge'
PatchType::values();                      // the four content types
PatchType::toOptions();                   // content type => label, for a select input
PatchType::validationRule();              // 'in:application/strategic-merge-patch+json,…'
PatchType::fromName('Json');              // PatchType::Json

// Build a patch from validated input
$patch = new KubernetesPatch(PatchType::from($request->input('type')), $request->input('body'));
```

## Scale and rollout restart

scale() merge-patches spec.replicas through the /scale subresource and returns the apiserver’s Scale answer — a DTO with name, namespace, replicas (desired), currentReplicas (observed), selector and resourceVersion — not the workload; find() the workload for that. rolloutRestart() stamps the pod template’s kubectl.kubernetes.io/restartedAt annotation with the current time — exactly what kubectl rollout restart does:

```php
// Scale via the /scale subresource. Returns the apiserver's Scale answer (a DTO), not the
// Deployment: $scale->replicas (desired), ->currentReplicas (observed), ->selector.
$scale = $cluster->deployments()->setNamespace('shop')->withName('checkout')->scale(5);
$cluster->statefulSets()->setNamespace('shop')->withName('search')->scale(3);

// Roll the pods by stamping the restartedAt annotation (like kubectl rollout restart).
$cluster->deployments()->setNamespace('shop')->withName('checkout')->rolloutRestart();
$cluster->daemonSets()->setNamespace('monitoring')->withName('node-agent')->rolloutRestart();

// Validate a write without persisting it by appending ?dryRun=All.
$preview = $cluster->deployments()->setNamespace('shop')->withName('checkout')->dryRun()->scale(5);
```

- scale() — deployments, replica sets, stateful sets and replication controllers.
- rolloutRestart() — deployments, stateful sets and daemon sets.
- dryRun() appends dryRun=All to every subsequent write — create, update, updateOrCreate, patch, delete, scale and rolloutRestart — so the apiserver validates the request and returns the result without persisting it. dryRun(false) switches it off again.

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