devantler-tech / devantler-tech/ksail

SetupInstance replaces the whole FluxInstance spec, dropping fields KSail does not model

Open
#6,455 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Go
Stars
165
Forks
12
Avg merge
5h 41m
Merged PRs (30d)
337

Description

> 🤖 Generated by the Agentic Engineer

## Evidence

`instanceManager.tryUpsert` fetches the existing FluxInstance into KSail's **typed** `FluxInstance`, assigns the whole spec, and issues a full `Update`:

```go
existing := &FluxInstance{}
err := fluxClient.Get(ctx, key, existing)
...
existing.Spec = desired.Spec
err = fluxClient.Update(ctx, existing)
```

KSail's `InstanceSpec` models **two** fields:

```go
type InstanceSpec struct {
Distribution Distribution `json:"distribution"`
Sync *Sync `json:"sync,omitempty"`
}
```

The flux-operator `FluxInstance` v1 CRD carries eight: `cluster`, `commonMetadata`, `components`, `distribution`, `kustomize`, `migrateResources`, `sharding`, `storage`, `sync`. A typed decode drops the six KSail does not model, and a full `Update` writes the object back without them.

## Why it matters

`spec.kustomize.patches` is the supported way to customise a Flux installation, and a consumer's patches there can be load-bearing. On the platform's production cluster the live FluxInstance carries six — controller replica counts, topology spread, and DNS `ndots` — one of which is annotated in-repo as having previously wedged reconciliation when resolved wrongly. `spec.components` and `spec.cluster` are likewise set there and unmodelled here.

`SetupInstance` is reached from `cluster update` through the component handlers (`reconcileWorkloadTag`, `reconcileFluxVersion`), so this is on the routine deploy path, not only bootstrap.

## What is verified vs inferred

**Verified by reading the source** at `26efa6b5`: the type has two fields; the update path assigns `existing.Spec = desired.Spec` and calls `Update`.

**Not yet observed live.** The production FluxInstance currently *has* all of those fields (generation 23, six patches present), so if the strip does occur it is being repaired — most plausibly by the Flux Kustomization that declares the FluxInstance in-repo, reconciling at a 1m interval. That would make the effect a transient window rather than permanent loss, which is still a window in which the controllers run without the patches.

**The first step is therefore measurement, not a fix**: confirm whether an `Update` from this path actually removes the unmodelled fields, and if so how long the gap lasts before GitOps restores it.

## Acceptance criteria

- [ ] A test demonstrates whether a FluxInstance carrying `spec.kustomize.patches`, `spec.components` and `spec.cluster` retains them across `SetupInstance`.
- [ ] If they are dropped, the upsert preserves unmodelled fields — e.g. a merge patch, or an unstructured read-modify-write — instead of a typed full replace.
- [ ] A consumer that declares a FluxInstance in Git is not fought by KSail on every update.

## Size

Small-to-medium. The measurement is small; the fix is a change of update strategy on one call path.

Found while fixing devantler-tech/platform#2922, whose fix adds one more (one-shot, convergent) trigger for this same path — see devantler-tech/ksail#6454.

Contributor guide

Open the contributing guide

Research direction

Start by tracing SetupInstance through instanceManager.tryUpsert and the component handlers reconcileWorkloadTag and reconcileFluxVersion at source revision 26efa6b5. Add a test for a FluxInstance containing spec.kustomize.patches, spec.components, and spec.cluster, then verify whether SetupInstance retains them. Done means unmodelled fields survive updates and a Git-declared FluxInstance is not repeatedly overwritten.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, kubernetes
Domain
devops, infrastructure
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.