Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 54 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ kind: PatchPlan
metadata:
name: talos-upgrade-v1.11.6
spec:
targetVersion: "ghcr.io/siderolabs/installer:v1.11.6"
# Target Talos image specification
target:
version: v1.11.6
source: ghcr # ghcr or factory

# Patch workers first, then control plane
patchWorkers: true
Expand Down Expand Up @@ -114,6 +117,50 @@ Apply the PatchPlan:
kubectl apply -f patchplan.yaml
```

**Example using Talos Factory images:**

The `target` specification uses individual fields to construct the factory image URL. The operator builds the full URL in the format:
```
factory.talos.dev/{installer}-installer[-secureboot]/{schematicID}:{version}
```

Field breakdown:
```yaml
target:
version: v1.11.6 # The Talos version tag
source: factory # Use factory.talos.dev (vs ghcr)
installer: nocloud # The installer type (aws, azure, nocloud, etc.)
schematicID: 95d432d6bb... # The factory schematic hash
secureBoot: true # Adds -secureboot suffix to installer
```

Full example:

```yaml
apiVersion: kangalpatch.ozalp.dk/v1alpha1
kind: PatchPlan
metadata:
name: talos-upgrade-factory
spec:
target:
version: v1.12.1
source: factory
installer: aws
schematicID: 376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba
secureBoot: true

patchWorkers: true
patchControlPlane: true
maxConcurrency: 2

talosConfig:
endpoints:
- 10.0.0.10:50000
secretRef:
name: talos-credentials
namespace: kangal-patch
```

### 3. Monitor Progress

Watch the upgrade progress:
Expand Down Expand Up @@ -160,7 +207,12 @@ kubectl patch patchplan simple-upgrade --type merge -p '{"spec":{"paused":false}

| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `targetVersion` | string | Target Talos version | Required |
| `target` | object | Target Talos image specification | Required |
| `target.version` | string | Talos version (e.g., v1.12.1) | Required |
| `target.source` | string | Image source: "ghcr" or "factory" | `ghcr` |
| `target.installer` | string | Installer type (e.g., "aws", "nocloud"). Required when source=factory | - |
| `target.schematicID` | string | Talos factory schematic ID. Required when source=factory | - |
| `target.secureBoot` | bool | Enable secure boot. Only applicable when source=factory | `false` |
| `nodeSelector` | map | Label selector for nodes | `{}` |
| `maxConcurrency` | int | Max nodes to patch concurrently | `1` |
| `maxFailures` | int | Max allowed failures before stopping | `0` |
Expand Down
4 changes: 2 additions & 2 deletions api/v1alpha1/patchjob_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ type PatchJobSpec struct {
// +kubebuilder:validation:Required
NodeName string `json:"nodeName"`

// TargetVersion is the Talos version to upgrade to
// Target defines the target Talos image specification
// +kubebuilder:validation:Required
TargetVersion string `json:"targetVersion"`
Target TargetSpec `json:"target"`

// PatchPlanRef references the parent PatchPlan
// +optional
Expand Down
34 changes: 31 additions & 3 deletions api/v1alpha1/patchplan_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,39 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// TargetSpec defines the target Talos image specification
type TargetSpec struct {
// Version is the Talos version (e.g., v1.12.1)
// +kubebuilder:validation:Required
Version string `json:"version"`

// Source specifies the image source: "factory" or "ghcr"
// +kubebuilder:validation:Enum=factory;ghcr
// +kubebuilder:default=ghcr
Source string `json:"source,omitempty"`

// Installer specifies the installer type (e.g., "aws", "azure", "nocloud")
// Required when source=factory
// +optional
Installer string `json:"installer,omitempty"`

// SchematicID is the Talos factory schematic ID
// Required when source=factory
// +optional
SchematicID string `json:"schematicID,omitempty"`

// SecureBoot enables secure boot for the installer image
// Only applicable when source=factory
// +kubebuilder:default=false
// +optional
SecureBoot bool `json:"secureBoot,omitempty"`
}

// PatchPlanSpec defines the desired state of PatchPlan
type PatchPlanSpec struct {
// TargetVersion is the Talos version to upgrade to
// Target defines the target Talos image specification
// +kubebuilder:validation:Required
TargetVersion string `json:"targetVersion"`
Target TargetSpec `json:"target"`

// NodeSelector selects which nodes to patch (label selector)
// +optional
Expand Down Expand Up @@ -155,7 +183,7 @@ type PatchPlanStatus struct {
// +kubebuilder:validation:Enum=Pending;InProgress;Paused;Completed;Failed
Phase PatchPhase `json:"phase,omitempty"`

// TargetVersion is the display version extracted from spec.targetVersion
// TargetVersion is the display version extracted from spec.target
// +optional
TargetVersion string `json:"targetVersion,omitempty"`

Expand Down
17 changes: 17 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 34 additions & 4 deletions config/crd/bases/kangalpatch.ozalp.dk_patchjobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,42 @@ spec:
patchPlanRef:
description: PatchPlanRef references the parent PatchPlan
type: string
targetVersion:
description: TargetVersion is the Talos version to upgrade to
type: string
target:
description: Target defines the target Talos image specification
properties:
installer:
description: |-
Installer specifies the installer type (e.g., "aws", "azure", "nocloud")
Required when source=factory
type: string
schematicID:
description: |-
SchematicID is the Talos factory schematic ID
Required when source=factory
type: string
secureBoot:
default: false
description: |-
SecureBoot enables secure boot for the installer image
Only applicable when source=factory
type: boolean
source:
default: ghcr
description: 'Source specifies the image source: "factory" or
"ghcr"'
enum:
- factory
- ghcr
type: string
version:
description: Version is the Talos version (e.g., v1.12.1)
type: string
required:
- version
type: object
required:
- nodeName
- targetVersion
- target
type: object
status:
description: PatchJobStatus defines the observed state of PatchJob
Expand Down
40 changes: 35 additions & 5 deletions config/crd/bases/kangalpatch.ozalp.dk_patchplans.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,41 @@ spec:
- name
type: object
type: object
targetVersion:
description: TargetVersion is the Talos version to upgrade to
type: string
target:
description: Target defines the target Talos image specification
properties:
installer:
description: |-
Installer specifies the installer type (e.g., "aws", "azure", "nocloud")
Required when source=factory
type: string
schematicID:
description: |-
SchematicID is the Talos factory schematic ID
Required when source=factory
type: string
secureBoot:
default: false
description: |-
SecureBoot enables secure boot for the installer image
Only applicable when source=factory
type: boolean
source:
default: ghcr
description: 'Source specifies the image source: "factory" or
"ghcr"'
enum:
- factory
- ghcr
type: string
version:
description: Version is the Talos version (e.g., v1.12.1)
type: string
required:
- version
type: object
required:
- targetVersion
- target
type: object
status:
description: PatchPlanStatus defines the observed state of PatchPlan
Expand Down Expand Up @@ -295,7 +325,7 @@ spec:
format: date-time
type: string
targetVersion:
description: TargetVersion is the display version extracted from spec.targetVersion
description: TargetVersion is the display version extracted from spec.target
type: string
totalNodes:
description: TotalNodes is the total number of nodes selected for
Expand Down
7 changes: 6 additions & 1 deletion config/samples/controlplane-only.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ metadata:
name: controlplane-only
spec:
# Target version
targetVersion: "factory.talos.dev/nocloud-installer-secureboot/95d432d6bb450a67e801a6ae77c96a67e38820b62ba4159ae7e997e1695207f7:v1.11.6"
target:
version: v1.11.6
source: factory
installer: nocloud
schematicID: 95d432d6bb450a67e801a6ae77c96a67e38820b62ba4159ae7e997e1695207f7
secureBoot: true

# Only patch control plane nodes
patchControlPlane: true
Expand Down
7 changes: 6 additions & 1 deletion config/samples/maintenance-window.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ metadata:
name: simple-upgrade-maintenance
spec:
# Target Talos version to upgrade to
targetVersion: "factory.talos.dev/nocloud-installer-secureboot/95d432d6bb450a67e801a6ae77c96a67e38820b62ba4159ae7e997e1695207f7:v1.11.6"
target:
version: v1.11.6
source: factory
installer: nocloud
schematicID: 95d432d6bb450a67e801a6ae77c96a67e38820b62ba4159ae7e997e1695207f7
secureBoot: true

# Node selection
nodeSelector:
Expand Down
7 changes: 6 additions & 1 deletion config/samples/simple-upgrade.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ metadata:
name: simple-upgrade
spec:
# Target Talos version to upgrade to
targetVersion: "factory.talos.dev/nocloud-installer-secureboot/95d432d6bb450a67e801a6ae77c96a67e38820b62ba4159ae7e997e1695207f7:v1.11.6"
target:
version: v1.11.6
source: factory
installer: nocloud
schematicID: 95d432d6bb450a67e801a6ae77c96a67e38820b62ba4159ae7e997e1695207f7
secureBoot: true

# Node selection
nodeSelector:
Expand Down
10 changes: 8 additions & 2 deletions controllers/patchjob_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func (r *PatchJobReconciler) initJob(ctx context.Context, patchJob *patchv1alpha
return r.failJob(ctx, original, patchJob, "failed to get current version", err)
}

targetVersion := patchutil.ExtractVersion(patchJob.Spec.TargetVersion)
targetVersion := patchJob.Spec.Target.Version

// Check if already at target version
if currentVersion == targetVersion {
Expand Down Expand Up @@ -347,8 +347,14 @@ func (r *PatchJobReconciler) startUpgrade(ctx context.Context, patchJob *patchv1
}
defer talosClient.Close()

// Build the installer image URL
installerImage, err := patchutil.BuildInstallerImage(patchJob.Spec.Target)
if err != nil {
return r.failJob(ctx, original, patchJob, "failed to build installer image", err)
}

// Initiate upgrade
if err := talosClient.Upgrade(ctx, patchJob.Spec.NodeName, patchJob.Spec.TargetVersion); err != nil {
if err := talosClient.Upgrade(ctx, patchJob.Spec.NodeName, installerImage); err != nil {
return r.failJob(ctx, original, patchJob, "failed to start upgrade", err)
}

Expand Down
8 changes: 4 additions & 4 deletions controllers/patchplan_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (r *PatchPlanReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
// Update status counts and total nodes
original := patchPlan.DeepCopy()
patchPlan.Status.TotalNodes = len(targetNodes)
patchPlan.Status.TargetVersion = patchutil.ExtractVersion(patchPlan.Spec.TargetVersion)
patchPlan.Status.TargetVersion = patchPlan.Spec.Target.Version
patchPlan.Status.CompletedNodes = jobSummary.Completed
patchPlan.Status.FailedNodes = jobSummary.Failed

Expand Down Expand Up @@ -400,9 +400,9 @@ func (r *PatchPlanReconciler) createPatchJob(ctx context.Context, patchPlan *pat
},
},
Spec: patchv1alpha1.PatchJobSpec{
NodeName: node.Name,
TargetVersion: patchPlan.Spec.TargetVersion,
PatchPlanRef: patchPlan.Name,
NodeName: node.Name,
Target: patchPlan.Spec.Target,
PatchPlanRef: patchPlan.Name,
},
}

Expand Down
Loading
Loading