WIP: etcd backups - #2952
Conversation
|
Pipeline controller notification For optional jobs, comment This repository is configured in: LGTM mode |
|
Skipping CI for Draft Pull Request. |
|
Hello @bhperry! Some important instructions when contributing to openshift/api: |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Central YAML (inherited) Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (16)
📒 Files selected for processing (9)
💤 Files with no reviewable changes (3)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughThe change replaces EtcdBackup PVC-only configuration with selectable PVC or local storage, adds node and backup result status fields, and introduces typed job references and condition reasons. It adds the cluster-scoped EtcdBackupPolicy API with scheduling, node selection, storage, retention, and status fields. Matching CRD schemas and scheme registrations are updated, while legacy Backup types are removed from config API registration and CRI-O credential provider types are registered. 🚥 Pre-merge checks | ✅ 13 | ❌ 2❌ Failed checks (2 inconclusive)
✅ Passed checks (13 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.12.2)Error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
operator/v1alpha1/types_etcdbackuppolicy.go (1)
34-44: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winNo format validation for
Schedule(cron) orTimeZone, unlike the legacy Backup CRD it supersedes.The pre-existing
config.openshift.ioBackup.spec.etcd.schedule/timeZonefields enforced cron and IANA-timezone patterns; the newEtcdBackupPolicySpecfields have no equivalent, so invalid cron expressions can be persisted.
[recommended_refactor_low_effort_note]🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@operator/v1alpha1/types_etcdbackuppolicy.go` around lines 34 - 44, Add equivalent validation markers to EtcdBackupPolicySpec.Schedule and TimeZone, enforcing valid cron expressions for Schedule and valid IANA time-zone names for TimeZone as the superseded Backup CRD did. Preserve Schedule as required and TimeZone as optional while ensuring invalid values are rejected during CRD validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@operator/v1alpha1/types_etcdbackup.go`:
- Around line 90-94: Update the kubebuilder XValidation message on the Path
field to say “path is immutable once set” instead of referring to “name”; leave
the immutability rule and other field metadata unchanged.
In `@operator/v1alpha1/types_etcdbackuppolicy.go`:
- Around line 52-55: Add non-negative validation for both NodeCount and
MaxQuantity using the appropriate Kubernetes validation markers, while
preserving NodeCount’s zero behavior for selecting all nodes. Mark NodeCount
with +optional consistently with its sibling fields, and update the
corresponding field declarations/documentation so generated CRD schemas reject
negative values.
- Around line 70-95: Update EtcdBackupPolicyRetentionRule to make the
discriminator enum accept both MaxQuantity and MaxSize. Add the corresponding
+unionMember tags to MaxQuantity and MaxSize, and add conditional XValidation
rules matching the EtcdBackupStorage union pattern so the field selected by Type
is required while the other is unset.
In `@payload-manifests/crds/0000_10_etcd_01_etcdbackups.crd.yaml`:
- Around line 88-94: Regenerate this CRD after correcting the kubebuilder
validation marker for the Path field in the EtcdBackup Go type, so the generated
validation message identifies “path” rather than “name.” Do not edit the
generated YAML directly.
---
Nitpick comments:
In `@operator/v1alpha1/types_etcdbackuppolicy.go`:
- Around line 34-44: Add equivalent validation markers to
EtcdBackupPolicySpec.Schedule and TimeZone, enforcing valid cron expressions for
Schedule and valid IANA time-zone names for TimeZone as the superseded Backup
CRD did. Preserve Schedule as required and TimeZone as optional while ensuring
invalid values are rejected during CRD validation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: b85840b1-9249-43dc-8ef7-89d067ce8593
⛔ Files ignored due to path filters (16)
config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_backups.crd.yamlis excluded by!**/zz_generated.crd-manifests/*config/v1alpha1/zz_generated.deepcopy.gois excluded by!**/zz_generated*config/v1alpha1/zz_generated.featuregated-crd-manifests.yamlis excluded by!**/zz_generated*config/v1alpha1/zz_generated.featuregated-crd-manifests/backups.config.openshift.io/AutomatedEtcdBackup.yamlis excluded by!**/zz_generated.featuregated-crd-manifests/**config/v1alpha1/zz_generated.model_name.gois excluded by!**/zz_generated*config/v1alpha1/zz_generated.swagger_doc_generated.gois excluded by!**/zz_generated*openapi/generated_openapi/zz_generated.openapi.gois excluded by!openapi/**,!**/zz_generated*openapi/openapi.jsonis excluded by!openapi/**operator/v1alpha1/zz_generated.crd-manifests/0000_10_etcd_01_etcdbackuppolicies.crd.yamlis excluded by!**/zz_generated.crd-manifests/*operator/v1alpha1/zz_generated.crd-manifests/0000_10_etcd_01_etcdbackups.crd.yamlis excluded by!**/zz_generated.crd-manifests/*operator/v1alpha1/zz_generated.deepcopy.gois excluded by!**/zz_generated*operator/v1alpha1/zz_generated.featuregated-crd-manifests.yamlis excluded by!**/zz_generated*operator/v1alpha1/zz_generated.featuregated-crd-manifests/etcdbackuppolicies.operator.openshift.io/AutomatedEtcdBackup.yamlis excluded by!**/zz_generated.featuregated-crd-manifests/**operator/v1alpha1/zz_generated.featuregated-crd-manifests/etcdbackups.operator.openshift.io/AutomatedEtcdBackup.yamlis excluded by!**/zz_generated.featuregated-crd-manifests/**operator/v1alpha1/zz_generated.model_name.gois excluded by!**/zz_generated*operator/v1alpha1/zz_generated.swagger_doc_generated.gois excluded by!**/zz_generated*
📒 Files selected for processing (7)
config/v1alpha1/register.goconfig/v1alpha1/types_backup.gooperator/v1alpha1/register.gooperator/v1alpha1/types_etcdbackup.gooperator/v1alpha1/types_etcdbackuppolicy.gopayload-manifests/crds/0000_10_config-operator_01_backups.crd.yamlpayload-manifests/crds/0000_10_etcd_01_etcdbackups.crd.yaml
💤 Files with no reviewable changes (2)
- config/v1alpha1/types_backup.go
- config/v1alpha1/register.go
8887fba to
4ea684c
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@operator/v1alpha1/types_etcdbackup.go`:
- Around line 128-131: Change the FileSize field in the backup status type from
resource.Quantity to *resource.Quantity so an unset optional value is omitted by
json:"fileSize,omitempty". Preserve its existing JSON tag, validation markers,
and file-size semantics.
- Around line 106-111: The optional Conditions field in the etcd backup status
currently lacks omission behavior for nil slices. Update Conditions to use the
existing JSON tag with omitempty, while preserving its list validation markers
and type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: b2e25909-3b06-43f8-817c-6c83ab7d986b
⛔ Files ignored due to path filters (16)
config/v1alpha1/zz_generated.crd-manifests/0000_10_config-operator_01_backups.crd.yamlis excluded by!**/zz_generated.crd-manifests/*config/v1alpha1/zz_generated.deepcopy.gois excluded by!**/zz_generated*config/v1alpha1/zz_generated.featuregated-crd-manifests.yamlis excluded by!**/zz_generated*config/v1alpha1/zz_generated.featuregated-crd-manifests/backups.config.openshift.io/AutomatedEtcdBackup.yamlis excluded by!**/zz_generated.featuregated-crd-manifests/**config/v1alpha1/zz_generated.model_name.gois excluded by!**/zz_generated*config/v1alpha1/zz_generated.swagger_doc_generated.gois excluded by!**/zz_generated*openapi/generated_openapi/zz_generated.openapi.gois excluded by!openapi/**,!**/zz_generated*openapi/openapi.jsonis excluded by!openapi/**operator/v1alpha1/zz_generated.crd-manifests/0000_10_etcd_01_etcdbackuppolicies.crd.yamlis excluded by!**/zz_generated.crd-manifests/*operator/v1alpha1/zz_generated.crd-manifests/0000_10_etcd_01_etcdbackups.crd.yamlis excluded by!**/zz_generated.crd-manifests/*operator/v1alpha1/zz_generated.deepcopy.gois excluded by!**/zz_generated*operator/v1alpha1/zz_generated.featuregated-crd-manifests.yamlis excluded by!**/zz_generated*operator/v1alpha1/zz_generated.featuregated-crd-manifests/etcdbackuppolicies.operator.openshift.io/AutomatedEtcdBackup.yamlis excluded by!**/zz_generated.featuregated-crd-manifests/**operator/v1alpha1/zz_generated.featuregated-crd-manifests/etcdbackups.operator.openshift.io/AutomatedEtcdBackup.yamlis excluded by!**/zz_generated.featuregated-crd-manifests/**operator/v1alpha1/zz_generated.model_name.gois excluded by!**/zz_generated*operator/v1alpha1/zz_generated.swagger_doc_generated.gois excluded by!**/zz_generated*
📒 Files selected for processing (9)
config/v1alpha1/register.goconfig/v1alpha1/types_backup.gohack/update-payload-crds.shoperator/v1alpha1/register.gooperator/v1alpha1/types_etcdbackup.gooperator/v1alpha1/types_etcdbackuppolicy.gopayload-manifests/crds/0000_10_config-operator_01_backups.crd.yamlpayload-manifests/crds/0000_10_etcd_01_etcdbackuppolicies.crd.yamlpayload-manifests/crds/0000_10_etcd_01_etcdbackups.crd.yaml
💤 Files with no reviewable changes (3)
- config/v1alpha1/register.go
- payload-manifests/crds/0000_10_config-operator_01_backups.crd.yaml
- config/v1alpha1/types_backup.go
🚧 Files skipped from review as they are similar to previous changes (3)
- payload-manifests/crds/0000_10_etcd_01_etcdbackups.crd.yaml
- operator/v1alpha1/register.go
- operator/v1alpha1/types_etcdbackuppolicy.go
| // conditions provide details on the status of the etcd backup job. | ||
| // +kubebuilder:validation:Optional | ||
| // +listType=map | ||
| // +listMapKey=type | ||
| // +optional | ||
| Conditions []metav1.Condition `json:"conditions,omitempty"` | ||
| Conditions []metav1.Condition `json:"conditions"` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify convention: other Condition slice fields in this repo keep omitempty despite listType=map.
rg -n -B2 'Conditions \[\]metav1.Condition' --type goRepository: openshift/api
Length of output: 151
🏁 Script executed:
#!/bin/bash
set -u
echo "## candidate files"
git ls-files | rg '(^|/)types_etcdbackup\.go$|types.*etcd|etcdbackup' | head -100
echo
echo "## etcdbackup types outline/content around Conditions"
while IFS= read -r f; do
echo "--- $f"
wc -l "$f"
sed -n '1,180p' "$f" | cat -n
done < <(git ls-files | rg '(^|/)types_etcdbackup\.go$')
echo
echo "## Condition slice declarations with omitempty status"
python3 - <<'PY'
import pathlib, re
for path in pathlib.Path('.').rglob('*.go'):
if '.git' in path.parts: continue
text=path.read_text()
for i,line in enumerate(text.splitlines(),1):
if re.search(r'(?m)^\s*Conditions\s+\[\]metav1\.Condition', line):
omitempty='omitempty' in line.split('`',1)[1] if '`' in line else False
print(f"{path}:{i}: omitempty={omitempty}: {line.strip()}")
PY
echo
echo "## JSON marshaling behavior for nil vs empty []metav1.Condition-like slices"
python3 - <<'PY'
import json
for value in [None, []]:
print(json.dumps({"conditions": value}))
PYRepository: openshift/api
Length of output: 13261
🏁 Script executed:
#!/bin/bash
set -u
echo "## operator/v1alpha1/types_etcdbackup.go lines 1-140"
sed -n '1,140p' operator/v1alpha1/types_etcdbackup.go | cat -n
echo
echo "## CRD openAPIV3Schema for EtcdBackup.conditions"
python3 - <<'PY'
import pathlib, yaml
for p in pathlib.Path('operator/v1alpha1/zz_generated.crd-manifests', 'payload-manifests/crds').glob('*etcdbackups*.yaml'):
text=p.read_text()
docs=text.split('---')
print(f'--- {p} ---')
for doc in docs:
if not doc.strip(): continue
data=yaml.safe_load(doc)
if not data or data.get('apiVersion') != 'apiextensions.k8s.io/v1': continue
name = (data.get('metadata') or {}).get('name', '')
if 'etcdbackups' in name:
try:
schema=data['spec']['versions'][0]['schema']['openAPIV3Schema']
except Exception as e:
print("schema access failed:", e)
continue
# print relevant schema paths
import json
paths=['definitions','$defs','properties','status','properties','conditions','x-kubernetes-list-map-keys','x-kubernetes-list-type']
print(name)
j=json.dumps(schema, sort_keys=True, indent=2)
for term in ['properties', 'status', 'conditions', 'type', 'items', 'title', 'nullable']:
if term in j:
print(term)
PYRepository: openshift/api
Length of output: 6732
🏁 Script executed:
#!/bin/bash
set -u
echo "## CRD files for EtcdBackup conditions"
python3 - <<'PY'
import pathlib
for p in [
pathlib.Path('operator/v1alpha1/zz_generated.crd-manifests/0000_10_etcd_01_etcdbackups.crd.yaml'),
pathlib.Path('payload-manifests/crds/0000_10_etcd_01_etcdbackups.crd.yaml'),
]:
text=p.read_text()
print(f'--- {p} ---')
lines=text.splitlines()
start=None
in_conds=False
for i,l in enumerate(lines,1):
if " conditions:" in l or " conditions:" in l:
in_conds=True
start=max(1,i-10)
if in_conds and i <= start+80:
print(f"{i:4}: {l}")
if in_conds and i > 200:
break
PY
echo
echo "## generated CRD schema nullability hints for conditions"
rg -n -C 4 'conditions:' operator/v1alpha1/zz_generated.crd-manifests/0000_10_etcd_01_etcdbackups.crd.yaml payload-manifests/crds/0000_10_etcd_01_etcdbackups.crd.yamlRepository: openshift/api
Length of output: 10683
🌐 Web query:
Kubernetes CRD structural schema arrays omit null listType map x-kubernetes-list-type x-kubernetes-list-map-keys
💡 Result:
In Kubernetes Custom Resource Definition (CRD) structural schemas, the x-kubernetes-list-type and x-kubernetes-list-map-keys extensions are used to define the behavior and topology of arrays, particularly for Server-Side Apply [1][2]. x-kubernetes-list-type This extension defines the topology of a list and must be one of three values: 1. map: The list elements act like map entries indexed by one or more keys [3][1]. Order is preserved, and unique keys ensure correct merging [2]. This must only be used on lists of objects [3][4]. 2. set: The list acts as a set where all elements must be unique [3][2]. Elements must be scalars, or objects/arrays marked with x-kubernetes-map-type or x-kubernetes-list-type as "atomic" [3][4]. 3. atomic: The entire list is treated as a single entity (like a scalar). Updates replace the entire list [3][1]. If not specified, this is the default behavior for arrays [2][4]. x-kubernetes-list-map-keys This extension is required when x-kubernetes-list-type is set to "map" [3][4]. It specifies an array of strings representing the fields within the list's child objects that serve as the unique keys [5][1]. These key fields must be scalar types and cannot be nested [3][2]. For reliable identification of list items, the specified key properties should either be marked as required or have a default value [2][4]. Null values in arrays Regarding null values in arrays, CRD structural schemas support the nullable: true attribute for array items [6][7]. While early implementations or related utilities (such as older versions of json-patch) experienced issues with dropping nulls, modern Kubernetes versions support nullability, allowing null values to be represented and preserved in lists [6][8]. To allow an explicit "null" as a valid value, nullable: true must be applied to the item schema [9][8]. Summary of Key Constraints: - x-kubernetes-list-map-keys can only be used when x-kubernetes-list-type is "map" [5][4]. - Keys for "map" lists must be scalar types [3][2]. - Atomic is the default if no list type is defined [2][4]. - Structural schemas require that all properties be explicitly defined and conform to structural rules (no logical junctors like anyOf/oneOf at the top level of schema branches) [10][7].
Citations:
- 1: https://kubernetes.io/docs/reference/using-api/server-side-apply/
- 2: https://kubernetes.io/docs/reference/kubernetes-api/apiextensions/custom-resource-definition-v1/
- 3: https://github.com/kubernetes/apiextensions-apiserver/blob/v0.35.3/pkg/apis/apiextensions/types_jsonschema.go
- 4: https://dev-k8sref-io.web.app/docs/common-definitions/jsonschemaprops-/
- 5: https://github.com/kubernetes-sigs/controller-tools/blob/master/pkg/crd/markers/topology.go
- 6: CustomResources dropping "null" values from arrays kubernetes/kubernetes#98080
- 7: https://kubernetes.io/blog/2019/06/20/crd-structural-schema/
- 8: apiextensions: add nullable support to OpenAPI v3 validations kubernetes/kubernetes#74804
- 9: https://github.com/kubernetes/community/blob/main/contributors/devel/sig-architecture/api-conventions.md
- 10: https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2335-vanilla-crd-openapi-subset-structural-schemas
Keep omitempty on the optional conditions field.
The field is marked +optional, but json:"conditions" serializes a nil slice as null. The generated CRD schema has type: array without nullable, so this makes the optional field non-null; keep the existing generated convention for list-typed optional conditions with json:"conditions,omitempty".
🐛 Proposed fix
// conditions provide Details on the status of the etcd backup job.
// +kubebuilder:validation:Optional
// +listType=map
// +listMapKey=type
// +optional
- Conditions []metav1.Condition `json:"conditions"`
+ Conditions []metav1.Condition `json:"conditions,omitempty"`📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // conditions provide details on the status of the etcd backup job. | |
| // +kubebuilder:validation:Optional | |
| // +listType=map | |
| // +listMapKey=type | |
| // +optional | |
| Conditions []metav1.Condition `json:"conditions,omitempty"` | |
| Conditions []metav1.Condition `json:"conditions"` | |
| // conditions provide details on the status of the etcd backup job. | |
| // +kubebuilder:validation:Optional | |
| // +listType=map | |
| // +listMapKey=type | |
| // +optional | |
| Conditions []metav1.Condition `json:"conditions,omitempty"` |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@operator/v1alpha1/types_etcdbackup.go` around lines 106 - 111, The optional
Conditions field in the etcd backup status currently lacks omission behavior for
nil slices. Update Conditions to use the existing JSON tag with omitempty, while
preserving its list validation markers and type.
| // fileSize is the size of the backup file on the storage backend. | ||
| // +kubebuilder:validation:Optional | ||
| // +optional | ||
| FileSize resource.Quantity `json:"fileSize,omitempty"` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check existing convention for optional resource.Quantity fields in this repo (pointer vs value).
rg -n '\*resource\.Quantity' --type go
rg -n 'resource\.Quantity `json:"[a-zA-Z]+,omitempty"`' --type goRepository: openshift/api
Length of output: 151
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and inspect the target type and nearby Quantity fields without executing repo code.
if [ -f operator/v1alpha1/types_etcdbackup.go ]; then
echo "== target file line count =="
wc -l operator/v1alpha1/types_etcdbackup.go
echo "== target file context =="
sed -n '100,155p' operator/v1alpha1/types_etcdbackup.go | nl -ba -v100
else
echo "target file not found"
fd -a 'types_etcdbackup\.go$' .
fi
echo "== all Quantity field declarations in repo =="
rg -n 'resource\.Quantity `json:"[A-Za-z]+,omitempty"`|`json:"[A-Za-z]+,omitempty"[\s\S]*resource\.Quantity' --type go || true
echo "== pointer Quantity declarations in repo =="
rg -n '\*resource\.Quantity' --type go || true
echo "== go json omitempty behavior for non-pointer Quantity =="
go env GOPATH GOROOT 2>/dev/null || true
cat >/tmp/quantity_omitempty_probe.go <<'EOF'
package main
import (
"encoding/json"
"fmt"
"k8s.io/apimachinery/pkg/api/resource"
)
type FileSizeValue struct {
FileSize resource.Quantity `json:"fileSize,omitempty"`
}
type FileSizePointer struct {
FileSize *resource.Quantity `json:"fileSize,omitempty"`
}
func mustMarshal(v any) string {
b, err := json.Marshal(v)
if err != nil {
panic(err)
}
return string(b)
}
func main() {
q := resource.Quantity{}
fmt.Println(mustMarshal(FileSizeValue{}))
fmt.Println(mustMarshal(FileSizePointer{}))
ptr := &q
fmt.Println(mustMarshal(FileSizePointer{FileSize: ptr}))
}
EOF
go run /tmp/quantity_omitempty_probe.goRepository: openshift/api
Length of output: 288
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== target file context =="
sed -n '100,155p' operator/v1alpha1/types_etcdbackup.go || true
echo "== all Quantity field declarations using omitempty =="
rg -n 'resource\.Quantity `json:"[A-Za-z]+,omitempty"`|`json:"[A-Za-z]+,omitempty"[\s\S]*resource\.Quantity' --type go || true
echo "== pointer Quantity declarations in repo =="
rg -n '\*resource\.Quantity' --type go || true
echo "== go availability =="
command -v go || true
go env GOPATH GOROOT 2>/dev/null || true
echo "== behavior probe =="
cat >/tmp/quantity_omitempty_probe.go <<'EOF'
package main
import (
"encoding/json"
"fmt"
"k8s.io/apimachinery/pkg/api/resource"
)
type FileSizeValue struct {
FileSize resource.Quantity `json:"fileSize,omitempty"`
}
type FileSizePointer struct {
FileSize *resource.Quantity `json:"fileSize,omitempty"`
}
func mustMarshal(v any) string {
b, err := json.Marshal(v)
if err != nil {
panic(err)
}
return string(b)
}
func main() {
fmt.Println("zero-valued value:", mustMarshal(FileSizeValue{}))
fmt.Println("zero-valued pointer:", mustMarshal(FileSizePointer{}))
val := resource.Quantity{}
fmt.Println("non-nil zero-valued pointer:", mustMarshal(FileSizePointer{FileSize: &val}))
}
EOF
if command -v go >/dev/null 2>&1; then
go run /tmp/quantity_omitempty_probe.go
else
echo "go not available"
fiRepository: openshift/api
Length of output: 2005
Make FileSize a pointer so omitempty works for an optional quantity.
resource.Quantity is a non-pointer struct, so json:"fileSize,omitempty" won’t omit the zero value (it still serializes "0"). Use *resource.Quantity for this optional status field so it is omitted when unset.
🐛 Proposed fix
// fileSize is the size of the backup file on the storage backend.
// +kubebuilder:validation:Optional
// +optional
- FileSize resource.Quantity `json:"fileSize,omitempty"`
+ FileSize *resource.Quantity `json:"fileSize,omitempty"`📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // fileSize is the size of the backup file on the storage backend. | |
| // +kubebuilder:validation:Optional | |
| // +optional | |
| FileSize resource.Quantity `json:"fileSize,omitempty"` | |
| // fileSize is the size of the backup file on the storage backend. | |
| // +kubebuilder:validation:Optional | |
| // +optional | |
| FileSize *resource.Quantity `json:"fileSize,omitempty"` |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@operator/v1alpha1/types_etcdbackup.go` around lines 128 - 131, Change the
FileSize field in the backup status type from resource.Quantity to
*resource.Quantity so an unset optional value is omitted by
json:"fileSize,omitempty". Preserve its existing JSON tag, validation markers,
and file-size semantics.
No description provided.