Conversation
Signed-off-by: Joseph <jvaikath@redhat.com>
Signed-off-by: Joseph <jvaikath@redhat.com>
Signed-off-by: Joseph <jvaikath@redhat.com>
Signed-off-by: Joseph <jvaikath@redhat.com>
📝 WalkthroughWalkthroughThis PR refactors NABSL request command handling by removing namespace flag support, eliminating validation hooks, repositioning UUID/name lookups to use direct admin namespace queries, improving output formatting with color and alignment, removing unused CLI commands, and pruning indirect dependencies. Changes
Sequence Diagram(s)sequenceDiagram
actor Client as CLI Client
participant Find as FindNABSL<br/>RequestByNameOrUUID
participant API as Admin Namespace<br/>API Server
participant Desc as Describe Output
Client->>Find: Resolve UUID_Name to request name
Find->>API: Get request by UUID
alt UUID found
API-->>Find: Return request
else UUID not found
Find->>API: List all requests in namespace
API-->>Find: Return request list
Find->>Find: Match on SourceNonAdminBSL.Name
end
Find-->>Client: Return canonical request name
Client->>API: Get full request details
API-->>Client: Return request object
Client->>Desc: Format and print with structure
Desc->>Desc: Apply color to phase
Desc->>Desc: Align labels/annotations
Desc-->>Client: Output formatted description
sequenceDiagram
actor Client as CLI Client
participant Find as FindNABSL<br/>RequestByNameOrUUID
participant API as Admin Namespace<br/>API Server
participant Output as Output Formatter
Client->>Find: Resolve name or UUID
Find->>API: Attempt Get by UUID
alt Found by UUID
API-->>Find: Return single request
Find-->>Client: Return request name
else Not found
Find->>API: List all requests in admin namespace
API-->>Find: Return filtered list
Find-->>Client: Return matching request name
end
Client->>API: Get or List requests
API-->>Client: Return result
Client->>Output: Format for display
Output-->>Client: Rendered output
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
Signed-off-by: Joseph <jvaikath@redhat.com>
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cmd/shared/nabsl_requests.go (1)
36-50:⚠️ Potential issue | 🟠 MajorReturn non-NotFound errors from the UUID lookup instead of silently falling back.
Currently, any
Geterror triggers a list fallback, which masks auth, network, and permission failures—allowing the function to surface a misleading "request not found" error at the end when the real problem was elsewhere.Only proceed to the fallback when the error is explicitly a NotFound error. For all other errors, return immediately with proper context.
🔧 Suggested fix
import ( "context" "fmt" kbclient "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/errors" nacv1alpha1 "github.com/migtools/oadp-non-admin/api/v1alpha1" ) @@ err := client.Get(ctx, kbclient.ObjectKey{ Name: nameOrUUID, Namespace: adminNamespace, }, &testRequest) if err == nil { return nameOrUUID, nil } + if !errors.IsNotFound(err) { + return "", fmt.Errorf("failed to get request %q: %w", nameOrUUID, err) + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/shared/nabsl_requests.go` around lines 36 - 50, The UUID lookup currently treats any error from client.Get(ctx, kbclient.ObjectKey{Name: nameOrUUID, Namespace: adminNamespace}, &testRequest) as a signal to fallback to listing; change this so only a NotFound error falls through to the list path—if client.Get returns a non-NotFound error (e.g. network/auth/permission error) return that error immediately with context (wrap/format it) instead of proceeding; keep the fallback behavior when the error is explicitly a NotFound (use the appropriate IsNotFound helper for your imports) and then continue with the existing client.List logic using requestList and adminNamespace.
🧹 Nitpick comments (1)
cmd/nabsl-request/approve.go (1)
87-89: Minor: Remove leftover empty line.Line 88 appears to be a leftover from removing the
Validate()call. Consider removing the empty line to keep the function body clean.🔧 Suggested cleanup
func (o *ApproveOptions) Run(c *cobra.Command, f client.Factory) error { - adminNS := f.Namespace()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@cmd/nabsl-request/approve.go` around lines 87 - 89, The function ApproveOptions.Run contains an extra blank line between the variable assignment adminNS := f.Namespace() and surrounding code; remove that leftover empty line so the function body is compact and the adminNS assignment is directly adjacent to the next statement.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@cmd/nabsl-request/describe.go`:
- Around line 108-184: The code dereferences spec.ObjectStorage without checking
for nil (when reading spec.ObjectStorage.Bucket and spec.ObjectStorage.Prefix),
which can panic for partial/invalid requests; update the block that handles
source.RequestedSpec (the Requested BackupStorageLocation Spec logic for
variable spec := source.RequestedSpec) to first check if spec.ObjectStorage !=
nil before accessing its fields and only print "Object Storage Bucket" and
"Prefix" when ObjectStorage is non-nil; retain printing other spec fields as-is
and ensure the nil check guards both Bucket and Prefix accesses.
---
Outside diff comments:
In `@cmd/shared/nabsl_requests.go`:
- Around line 36-50: The UUID lookup currently treats any error from
client.Get(ctx, kbclient.ObjectKey{Name: nameOrUUID, Namespace: adminNamespace},
&testRequest) as a signal to fallback to listing; change this so only a NotFound
error falls through to the list path—if client.Get returns a non-NotFound error
(e.g. network/auth/permission error) return that error immediately with context
(wrap/format it) instead of proceeding; keep the fallback behavior when the
error is explicitly a NotFound (use the appropriate IsNotFound helper for your
imports) and then continue with the existing client.List logic using requestList
and adminNamespace.
---
Nitpick comments:
In `@cmd/nabsl-request/approve.go`:
- Around line 87-89: The function ApproveOptions.Run contains an extra blank
line between the variable assignment adminNS := f.Namespace() and surrounding
code; remove that leftover empty line so the function body is compact and the
adminNS assignment is directly adjacent to the next statement.
| // Name and Namespace | ||
| fmt.Printf("Name: %s\n", request.Name) | ||
| fmt.Printf("Namespace: %s\n", request.Namespace) | ||
|
|
||
| // Labels | ||
| shared.PrintLabelsOrAnnotations(os.Stdout, "Labels: ", request.Labels) | ||
|
|
||
| fmt.Printf("Labels:\t%s\n", formatLabels(request.Labels)) | ||
| fmt.Printf("Annotations:\t%s\n", formatLabels(request.Annotations)) | ||
| // Annotations | ||
| shared.PrintLabelsOrAnnotations(os.Stdout, "Annotations: ", request.Annotations) | ||
|
|
||
| fmt.Printf("Phase:\t%s\n", request.Status.Phase) | ||
| fmt.Printf("\n") | ||
|
|
||
| // Phase (with color) | ||
| fmt.Printf("Phase: %s\n", shared.ColorizePhase(string(request.Status.Phase))) | ||
|
|
||
| fmt.Printf("\n") | ||
|
|
||
| // Approval Decision | ||
| if request.Spec.ApprovalDecision != "" { | ||
| fmt.Printf("Approval Decision:\t%s\n", request.Spec.ApprovalDecision) | ||
| fmt.Printf("Approval Decision: %s\n", request.Spec.ApprovalDecision) | ||
| fmt.Printf("\n") | ||
| } | ||
|
|
||
| // Requested NonAdminBackupStorageLocation | ||
| if request.Status.SourceNonAdminBSL != nil { | ||
| source := request.Status.SourceNonAdminBSL | ||
| fmt.Printf("Requested NonAdminBackupStorageLocation:\n") | ||
| fmt.Printf(" Name:\t%s\n", source.Name) | ||
| fmt.Printf(" Namespace:\t%s\n", source.Namespace) | ||
| fmt.Printf(" Name: %s\n", source.Name) | ||
| fmt.Printf(" Namespace: %s\n", source.Namespace) | ||
|
|
||
| if source.NACUUID != "" { | ||
| fmt.Printf(" NACUUID:\t%s\n", source.NACUUID) | ||
| fmt.Printf(" NACUUID: %s\n", source.NACUUID) | ||
| } | ||
|
|
||
| fmt.Printf("\n") | ||
|
|
||
| // Requested BackupStorageLocation Spec | ||
| if source.RequestedSpec != nil { | ||
| spec := source.RequestedSpec | ||
| fmt.Printf("Requested BackupStorageLocation Spec:\n") | ||
| fmt.Printf(" Provider:\t%s\n", spec.Provider) | ||
| fmt.Printf(" Object Storage Bucket:\t%s\n", spec.ObjectStorage.Bucket) | ||
| fmt.Printf(" Provider: %s\n", spec.Provider) | ||
| fmt.Printf(" Object Storage Bucket: %s\n", spec.ObjectStorage.Bucket) | ||
|
|
||
| if spec.ObjectStorage.Prefix != "" { | ||
| fmt.Printf(" Prefix:\t%s\n", spec.ObjectStorage.Prefix) | ||
| fmt.Printf(" Prefix: %s\n", spec.ObjectStorage.Prefix) | ||
| } | ||
|
|
||
| if len(spec.Config) > 0 { | ||
| fmt.Printf(" Config:\t%s\n", formatLabels(spec.Config)) | ||
| fmt.Printf(" Config:\n") | ||
| configKeys := make([]string, 0, len(spec.Config)) | ||
| for k := range spec.Config { | ||
| configKeys = append(configKeys, k) | ||
| } | ||
| sort.Strings(configKeys) | ||
| for _, k := range configKeys { | ||
| fmt.Printf(" %s: %s\n", k, spec.Config[k]) | ||
| } | ||
| } | ||
|
|
||
| if spec.AccessMode != "" { | ||
| fmt.Printf(" Access Mode:\t%s\n", spec.AccessMode) | ||
| fmt.Printf(" Access Mode: %s\n", spec.AccessMode) | ||
| } | ||
|
|
||
| if spec.BackupSyncPeriod != nil { | ||
| fmt.Printf(" Backup Sync Period:\t%s\n", spec.BackupSyncPeriod.String()) | ||
| fmt.Printf(" Backup Sync Period: %s\n", spec.BackupSyncPeriod.String()) | ||
| } | ||
|
|
||
| if spec.ValidationFrequency != nil { | ||
| fmt.Printf(" Validation Frequency:\t%s\n", spec.ValidationFrequency.String()) | ||
| fmt.Printf(" Validation Frequency: %s\n", spec.ValidationFrequency.String()) | ||
| } | ||
|
|
||
| fmt.Printf("\n") | ||
| } | ||
| } | ||
|
|
||
| fmt.Printf("Creation Timestamp:\t%s\n", request.CreationTimestamp.String()) | ||
| // Creation Timestamp | ||
| fmt.Printf("Creation Timestamp: %s\n", request.CreationTimestamp.Time.Format("2006-01-02 15:04:05 -0700 MST")) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
rg -n "type BackupStorageLocationSpec" -A 20 -B 2 -g '*.go'Repository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
rg -n "ObjectStorage" -B 2 -A 2 -g '*.go' | head -100Repository: migtools/oadp-cli
Length of output: 1589
🏁 Script executed:
fd -e go -type f | xargs grep -l "BackupStorageLocationSpec" | head -10Repository: migtools/oadp-cli
Length of output: 231
🏁 Script executed:
rg -n "ObjectStorage.*\*" -B 1 -A 1 -g '*.go'Repository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
rg -n "struct {" -A 30 | grep -A 30 "BackupStorageLocationSpec"Repository: migtools/oadp-cli
Length of output: 140
🏁 Script executed:
find . -name "*.go" -type f -exec grep -l "BackupStorageLocationSpec" {} \; | head -5Repository: migtools/oadp-cli
Length of output: 117
🏁 Script executed:
rg "BackupStorageLocationSpec\|ObjectStorage" ./cmd/nabsl-request/describe.go -B 2 -A 2Repository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
cat ./cmd/nabsl-request/describe.go | head -50Repository: migtools/oadp-cli
Length of output: 1579
🏁 Script executed:
rg "import" ./cmd/nabsl-request/describe.go -A 20Repository: migtools/oadp-cli
Length of output: 579
🏁 Script executed:
cat -n ./cmd/nabsl-request/describe.go | sed -n '130,160p'Repository: migtools/oadp-cli
Length of output: 1307
🏁 Script executed:
rg -n "spec.ObjectStorage" ./cmd/nabsl-request/describe.goRepository: migtools/oadp-cli
Length of output: 269
🏁 Script executed:
rg -n "RequestedSpec.*BackupStorageLocationSpec" . -B 2 -A 2 --type goRepository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
rg -n "type.*BackupStorageLocationSpec" . --type go -A 25Repository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
rg -n "ObjectStorage.*\*ObjectStorageLocation" . --type goRepository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
grep -r "ObjectStorage" ./cmd/non-admin/bsl/get.go -B 3 -A 3 | head -20Repository: migtools/oadp-cli
Length of output: 465
🏁 Script executed:
grep -r "ObjectStorage" . --include="*.go" | grep "type\|struct" | head -20Repository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
rg -n "\.ObjectStorage\s*\*" . --type go -B 2 -A 2Repository: migtools/oadp-cli
Length of output: 43
🏁 Script executed:
web_search
Velero BackupStorageLocationSpec ObjectStorage pointerRepository: migtools/oadp-cli
Length of output: 156
🌐 Web query:
Velero BackupStorageLocationSpec ObjectStorage field type
💡 Result:
In Velero’s Go API, .spec.objectStorage is a pointer to ObjectStorageLocation:
type StorageType struct { ObjectStorage *ObjectStorageLocation \json:"objectStorage"` }(andBackupStorageLocationSpecinlinesStorageType`). [1]
In the CRD/OpenAPI schema, .spec.objectStorage is an object of kind ObjectStorageLocation. [2][3]
Sources: [1] [2] [3]
🏁 Script executed:
rg -n "BackupStorageLocationSpec" . --type go -B 3 -A 15 | grep -A 15 "ObjectStorage"Repository: migtools/oadp-cli
Length of output: 2148
🏁 Script executed:
grep -n "source.RequestedSpec" ./cmd/nabsl-request/describe.go -B 5 -A 20Repository: migtools/oadp-cli
Length of output: 948
Guard against nil ObjectStorage in the requested spec.
spec.ObjectStorage is a pointer in the Velero BSL spec; if it's nil (invalid/partial request), dereferencing it at lines 149 and 151 will panic. Add a nil check before accessing its fields.
🛡️ Suggested fix
- fmt.Printf(" Provider: %s\n", spec.Provider)
- fmt.Printf(" Object Storage Bucket: %s\n", spec.ObjectStorage.Bucket)
-
- if spec.ObjectStorage.Prefix != "" {
- fmt.Printf(" Prefix: %s\n", spec.ObjectStorage.Prefix)
- }
+ fmt.Printf(" Provider: %s\n", spec.Provider)
+ if spec.ObjectStorage != nil {
+ fmt.Printf(" Object Storage Bucket: %s\n", spec.ObjectStorage.Bucket)
+ if spec.ObjectStorage.Prefix != "" {
+ fmt.Printf(" Prefix: %s\n", spec.ObjectStorage.Prefix)
+ }
+ } else {
+ fmt.Printf(" Object Storage Bucket: <none>\n")
+ }📝 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.
| // Name and Namespace | |
| fmt.Printf("Name: %s\n", request.Name) | |
| fmt.Printf("Namespace: %s\n", request.Namespace) | |
| // Labels | |
| shared.PrintLabelsOrAnnotations(os.Stdout, "Labels: ", request.Labels) | |
| fmt.Printf("Labels:\t%s\n", formatLabels(request.Labels)) | |
| fmt.Printf("Annotations:\t%s\n", formatLabels(request.Annotations)) | |
| // Annotations | |
| shared.PrintLabelsOrAnnotations(os.Stdout, "Annotations: ", request.Annotations) | |
| fmt.Printf("Phase:\t%s\n", request.Status.Phase) | |
| fmt.Printf("\n") | |
| // Phase (with color) | |
| fmt.Printf("Phase: %s\n", shared.ColorizePhase(string(request.Status.Phase))) | |
| fmt.Printf("\n") | |
| // Approval Decision | |
| if request.Spec.ApprovalDecision != "" { | |
| fmt.Printf("Approval Decision:\t%s\n", request.Spec.ApprovalDecision) | |
| fmt.Printf("Approval Decision: %s\n", request.Spec.ApprovalDecision) | |
| fmt.Printf("\n") | |
| } | |
| // Requested NonAdminBackupStorageLocation | |
| if request.Status.SourceNonAdminBSL != nil { | |
| source := request.Status.SourceNonAdminBSL | |
| fmt.Printf("Requested NonAdminBackupStorageLocation:\n") | |
| fmt.Printf(" Name:\t%s\n", source.Name) | |
| fmt.Printf(" Namespace:\t%s\n", source.Namespace) | |
| fmt.Printf(" Name: %s\n", source.Name) | |
| fmt.Printf(" Namespace: %s\n", source.Namespace) | |
| if source.NACUUID != "" { | |
| fmt.Printf(" NACUUID:\t%s\n", source.NACUUID) | |
| fmt.Printf(" NACUUID: %s\n", source.NACUUID) | |
| } | |
| fmt.Printf("\n") | |
| // Requested BackupStorageLocation Spec | |
| if source.RequestedSpec != nil { | |
| spec := source.RequestedSpec | |
| fmt.Printf("Requested BackupStorageLocation Spec:\n") | |
| fmt.Printf(" Provider:\t%s\n", spec.Provider) | |
| fmt.Printf(" Object Storage Bucket:\t%s\n", spec.ObjectStorage.Bucket) | |
| fmt.Printf(" Provider: %s\n", spec.Provider) | |
| fmt.Printf(" Object Storage Bucket: %s\n", spec.ObjectStorage.Bucket) | |
| if spec.ObjectStorage.Prefix != "" { | |
| fmt.Printf(" Prefix:\t%s\n", spec.ObjectStorage.Prefix) | |
| fmt.Printf(" Prefix: %s\n", spec.ObjectStorage.Prefix) | |
| } | |
| if len(spec.Config) > 0 { | |
| fmt.Printf(" Config:\t%s\n", formatLabels(spec.Config)) | |
| fmt.Printf(" Config:\n") | |
| configKeys := make([]string, 0, len(spec.Config)) | |
| for k := range spec.Config { | |
| configKeys = append(configKeys, k) | |
| } | |
| sort.Strings(configKeys) | |
| for _, k := range configKeys { | |
| fmt.Printf(" %s: %s\n", k, spec.Config[k]) | |
| } | |
| } | |
| if spec.AccessMode != "" { | |
| fmt.Printf(" Access Mode:\t%s\n", spec.AccessMode) | |
| fmt.Printf(" Access Mode: %s\n", spec.AccessMode) | |
| } | |
| if spec.BackupSyncPeriod != nil { | |
| fmt.Printf(" Backup Sync Period:\t%s\n", spec.BackupSyncPeriod.String()) | |
| fmt.Printf(" Backup Sync Period: %s\n", spec.BackupSyncPeriod.String()) | |
| } | |
| if spec.ValidationFrequency != nil { | |
| fmt.Printf(" Validation Frequency:\t%s\n", spec.ValidationFrequency.String()) | |
| fmt.Printf(" Validation Frequency: %s\n", spec.ValidationFrequency.String()) | |
| } | |
| fmt.Printf("\n") | |
| } | |
| } | |
| fmt.Printf("Creation Timestamp:\t%s\n", request.CreationTimestamp.String()) | |
| // Creation Timestamp | |
| fmt.Printf("Creation Timestamp: %s\n", request.CreationTimestamp.Time.Format("2006-01-02 15:04:05 -0700 MST")) | |
| // Name and Namespace | |
| fmt.Printf("Name: %s\n", request.Name) | |
| fmt.Printf("Namespace: %s\n", request.Namespace) | |
| // Labels | |
| shared.PrintLabelsOrAnnotations(os.Stdout, "Labels: ", request.Labels) | |
| // Annotations | |
| shared.PrintLabelsOrAnnotations(os.Stdout, "Annotations: ", request.Annotations) | |
| fmt.Printf("\n") | |
| // Phase (with color) | |
| fmt.Printf("Phase: %s\n", shared.ColorizePhase(string(request.Status.Phase))) | |
| fmt.Printf("\n") | |
| // Approval Decision | |
| if request.Spec.ApprovalDecision != "" { | |
| fmt.Printf("Approval Decision: %s\n", request.Spec.ApprovalDecision) | |
| fmt.Printf("\n") | |
| } | |
| // Requested NonAdminBackupStorageLocation | |
| if request.Status.SourceNonAdminBSL != nil { | |
| source := request.Status.SourceNonAdminBSL | |
| fmt.Printf("Requested NonAdminBackupStorageLocation:\n") | |
| fmt.Printf(" Name: %s\n", source.Name) | |
| fmt.Printf(" Namespace: %s\n", source.Namespace) | |
| if source.NACUUID != "" { | |
| fmt.Printf(" NACUUID: %s\n", source.NACUUID) | |
| } | |
| fmt.Printf("\n") | |
| // Requested BackupStorageLocation Spec | |
| if source.RequestedSpec != nil { | |
| spec := source.RequestedSpec | |
| fmt.Printf("Requested BackupStorageLocation Spec:\n") | |
| fmt.Printf(" Provider: %s\n", spec.Provider) | |
| if spec.ObjectStorage != nil { | |
| fmt.Printf(" Object Storage Bucket: %s\n", spec.ObjectStorage.Bucket) | |
| if spec.ObjectStorage.Prefix != "" { | |
| fmt.Printf(" Prefix: %s\n", spec.ObjectStorage.Prefix) | |
| } | |
| } else { | |
| fmt.Printf(" Object Storage Bucket: <none>\n") | |
| } | |
| if len(spec.Config) > 0 { | |
| fmt.Printf(" Config:\n") | |
| configKeys := make([]string, 0, len(spec.Config)) | |
| for k := range spec.Config { | |
| configKeys = append(configKeys, k) | |
| } | |
| sort.Strings(configKeys) | |
| for _, k := range configKeys { | |
| fmt.Printf(" %s: %s\n", k, spec.Config[k]) | |
| } | |
| } | |
| if spec.AccessMode != "" { | |
| fmt.Printf(" Access Mode: %s\n", spec.AccessMode) | |
| } | |
| if spec.BackupSyncPeriod != nil { | |
| fmt.Printf(" Backup Sync Period: %s\n", spec.BackupSyncPeriod.String()) | |
| } | |
| if spec.ValidationFrequency != nil { | |
| fmt.Printf(" Validation Frequency: %s\n", spec.ValidationFrequency.String()) | |
| } | |
| fmt.Printf("\n") | |
| } | |
| } | |
| // Creation Timestamp | |
| fmt.Printf("Creation Timestamp: %s\n", request.CreationTimestamp.Time.Format("2006-01-02 15:04:05 -0700 MST")) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@cmd/nabsl-request/describe.go` around lines 108 - 184, The code dereferences
spec.ObjectStorage without checking for nil (when reading
spec.ObjectStorage.Bucket and spec.ObjectStorage.Prefix), which can panic for
partial/invalid requests; update the block that handles source.RequestedSpec
(the Requested BackupStorageLocation Spec logic for variable spec :=
source.RequestedSpec) to first check if spec.ObjectStorage != nil before
accessing its fields and only print "Object Storage Bucket" and "Prefix" when
ObjectStorage is non-nil; retain printing other spec fields as-is and ensure the
nil check guards both Bucket and Prefix accesses.
Why the changes were made
make installrunsHow to test the changes made
oc oadp nabsl-request describeshould now work correctlySummary by CodeRabbit
Release Notes
New Features
Bug Fixes
Changes