netbox-community / netbox-community/netbox-chart

netbox-operator chart ships outdated CRDs, missing status.lastUpdated breaks operator change detection

Open
#1,347 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Mustache
Stars
357
Forks
186
Avg merge
1h 57m
Merged PRs (30d)
52

Description

### Summary

The CRDs bundled in the netbox-operator chart are older than the operator image the chart deploys. The Prefix, IpAddress and IpRange CRDs are missing the status.lastUpdated property, which the operator has been writing since v0.2.51. The API server prunes the field, and because the operator reads it back for change detection, every reconcile is treated as out of date.

### Versions

Chart netbox-operator 1.2.145, appVersion 0.2.65 (also reproduced on main).

### What happens

On every reconcile the operator logs:

```
{"level":"info","msg":"unknown field \"status.lastUpdated\"","controller":"prefix","controllerGroup":"netbox.dev","controllerKind":"Prefix"}
```

The custom resources still reach Ready=True, so at first glance this looks like a cosmetic warning.

### Why it is not cosmetic

The operator writes the field in prefix_controller.go:

```go
if netboxPrefixModel.LastUpdated.IsSet() {
o.Status.LastUpdated = metav1.NewTime(*netboxPrefixModel.LastUpdated.Get())
}
```

and reads it back in pkg/netbox/api/change_detection.go:

```go
func IsUpToDate(...) bool {
if statusLastUpdated.IsZero() {
return false
}
...
}
```

Since the CRD has no such property, the value is pruned on write and always reads back as zero. IsUpToDate therefore always returns false, so the early return in pkg/netbox/api/prefix.go is never taken:

```go
if IsUpToDate(ctx, *prefixToUpdate.LastUpdated.Get(), prefixV1.Status.LastUpdated, prefixV1.Status.Conditions, prefixV1.Generation) {
return nil, true, nil
}

//update prefix since it does exist
resp, err = c.updatePrefix(ctx, prefixToUpdate.Id, prefix)
```

The result is an unnecessary write to NetBox on every reconcile even when nothing changed, one NetBox changelog entry per write, and a NetBox side last_updated bump that feeds back into the next comparison. The same pattern exists in ip_address.go and ip_range.go.

### Root cause

The chart ships its own copy of the CRDs, and that copy has not been refreshed since May 2025 (commit 83c8831a, "Update operator & CRDs to v0.1.0-alpha.7"), while the operator appVersion has kept moving. status.lastUpdated was introduced in operator v0.2.51.

Confirmed by comparing the chart CRDs against the operator repository:

```
netbox-chart 1.2.145 charts/netbox-operator/crds/prefixes.yaml status: conditions, id, url
netbox-operator v0.2.65 config/crd/bases/netbox.dev_prefixes.yaml status: conditions, id, url, lastUpdated
```

### Suggested fix

Refresh charts/netbox-operator/crds from the operator release that matches appVersion, and ideally have the appVersion bump automation copy config/crd/bases in the same change so the two cannot drift again.

### Workaround

Skip the chart CRDs and apply the CRDs from the matching operator release instead. Applying them without skipping the chart CRDs is not enough, since the next sync restores the older schema and the field is pruned again.

Contributor guide

No contributing guide indexed for this repository

Research direction

Compare the chart CRDs under charts/netbox-operator/crds, especially prefixes.yaml and the corresponding IpAddress and IpRange files, with config/crd/bases in the matching netbox-operator release. Start by checking the appVersion and the v0.2.51 schema change; done means all three CRDs expose status.lastUpdated and the chart copy stays aligned with the deployed operator version.

Written by the indexing model from the issue text.

Assessment

Tech stack
helm, kubernetes
Domain
devops, infrastructure
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.