Skip to content

Commit 97caa86

Browse files
committed
add bucketaccess sidecar reconciliation
Implement the final portion of BucketAccess provisioning after handoff to the Sidecar. Signed-off-by: Blaine Gardner <blaine.gardner@ibm.com>
1 parent e8ad800 commit 97caa86

File tree

367 files changed

+5743
-34506
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

367 files changed

+5743
-34506
lines changed

client/apis/objectstorage/v1alpha2/definitions.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ const (
2525

2626
// Annotations
2727
const (
28+
// BucketClaimBeingDeletedAnnotation : This annotation is applied by the COSI Controller to a
29+
// Bucket when its BucketClaim is being deleted.
30+
BucketClaimBeingDeletedAnnotation = `objectstorage.k8.io/bucketclaim-being-deleted`
31+
2832
// HasBucketAccessReferencesAnnotation : This annotation is applied by the COSI Controller to a
2933
// BucketClaim when a BucketAccess that references the BucketClaim is created. The annotation
3034
// remains for as long as any BucketAccess references the BucketClaim. Once all BucketAccesses

controller/internal/reconciler/bucketaccess.go

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ import (
3636

3737
cosiapi "sigs.k8s.io/container-object-storage-interface/client/apis/objectstorage/v1alpha2"
3838
objectstoragev1alpha2 "sigs.k8s.io/container-object-storage-interface/client/apis/objectstorage/v1alpha2"
39+
"sigs.k8s.io/container-object-storage-interface/internal/bucketaccess"
3940
cosierr "sigs.k8s.io/container-object-storage-interface/internal/errors"
40-
"sigs.k8s.io/container-object-storage-interface/internal/handoff"
4141
cosipredicate "sigs.k8s.io/container-object-storage-interface/internal/predicate"
4242
)
4343

@@ -67,7 +67,7 @@ func (r *BucketAccessReconciler) Reconcile(ctx context.Context, req ctrl.Request
6767
return ctrl.Result{}, err
6868
}
6969

70-
if handoff.BucketAccessManagedBySidecar(access) {
70+
if bucketaccess.ManagedBySidecar(access) {
7171
logger.V(1).Info("not reconciling BucketAccess that should be managed by sidecar")
7272
return ctrl.Result{}, nil
7373
}
@@ -142,12 +142,12 @@ func (r *BucketAccessReconciler) reconcile(
142142
return cosierr.NonRetryableError(fmt.Errorf("deletion is not yet implemented")) // TODO
143143
}
144144

145-
needInit, err := needsControllerInitialization(&access.Status)
145+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status)
146146
if err != nil {
147147
logger.Error(err, "processed a degraded BucketAccess")
148148
return cosierr.NonRetryableError(fmt.Errorf("processed a degraded BucketAccess: %w", err))
149149
}
150-
if !needInit {
150+
if initialized {
151151
// BucketAccessClass info should only be copied to the BucketAccess status once, upon
152152
// initial provisioning. After the info is copied, make no attempt to fill in any missing or
153153
// lost info because we don't know whether the current Class is compatible with the info
@@ -244,38 +244,6 @@ func (r *BucketAccessReconciler) reconcile(
244244
return nil
245245
}
246246

247-
// Return true if the Controller needs to initialize the BucketAccess with BucketClaim and
248-
// BucketAccessClass info. Return false if required info is set.
249-
// Return an error if any required info is only partially set. This indicates some sort of
250-
// degradation or bug.
251-
func needsControllerInitialization(s *cosiapi.BucketAccessStatus) (bool, error) {
252-
requiredFields := map[string]bool{}
253-
requiredFieldIsSet := func(fieldName string, isSet bool) {
254-
requiredFields[fieldName] = isSet
255-
}
256-
257-
requiredFieldIsSet("status.accessedBuckets", len(s.AccessedBuckets) > 0)
258-
requiredFieldIsSet("status.driverName", s.DriverName != "")
259-
requiredFieldIsSet("status.authenticationType", string(s.AuthenticationType) != "")
260-
261-
set := []string{}
262-
for field, isSet := range requiredFields {
263-
if isSet {
264-
set = append(set, field)
265-
}
266-
}
267-
268-
if len(set) == 0 {
269-
return true, nil
270-
}
271-
272-
if len(set) == len(requiredFields) {
273-
return false, nil
274-
}
275-
276-
return false, fmt.Errorf("required Controller-managed fields are only partially set: %v", requiredFields)
277-
}
278-
279247
// Get all BucketClaims that this BucketAccess references.
280248
// If any claims don't exist, assume they don't exist YET; mark them nil in the resulting map
281249
// without treating nonexistence as an error.

controller/internal/reconciler/bucketaccess_test.go

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929
"k8s.io/apimachinery/pkg/types"
3030
"k8s.io/utils/ptr"
3131
cosiapi "sigs.k8s.io/container-object-storage-interface/client/apis/objectstorage/v1alpha2"
32-
"sigs.k8s.io/container-object-storage-interface/internal/handoff"
32+
"sigs.k8s.io/container-object-storage-interface/internal/bucketaccess"
3333
ctrl "sigs.k8s.io/controller-runtime"
3434
"sigs.k8s.io/controller-runtime/pkg/client"
3535
"sigs.k8s.io/controller-runtime/pkg/client/fake"
@@ -195,10 +195,10 @@ func TestBucketAccessReconcile(t *testing.T) {
195195
status.Parameters,
196196
)
197197

198-
assert.True(t, handoff.BucketAccessManagedBySidecar(access)) // MUST hand off to sidecar
199-
needInit, err := needsControllerInitialization(&access.Status) // MUST be fully initialized
198+
assert.True(t, bucketaccess.ManagedBySidecar(access)) // MUST hand off to sidecar
199+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST be fully initialized
200200
assert.NoError(t, err)
201-
assert.False(t, needInit)
201+
assert.True(t, initialized)
202202

203203
crw := &cosiapi.BucketClaim{}
204204
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -267,10 +267,10 @@ func TestBucketAccessReconcile(t *testing.T) {
267267
assert.Empty(t, status.AuthenticationType)
268268
assert.Empty(t, status.Parameters)
269269

270-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
271-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
270+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
271+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
272272
assert.NoError(t, err)
273-
assert.True(t, needInit)
273+
assert.False(t, initialized)
274274

275275
crw := &cosiapi.BucketClaim{}
276276
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -315,10 +315,10 @@ func TestBucketAccessReconcile(t *testing.T) {
315315
assert.Empty(t, status.AuthenticationType)
316316
assert.Empty(t, status.Parameters)
317317

318-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
319-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
318+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
319+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
320320
assert.NoError(t, err)
321-
assert.True(t, needInit)
321+
assert.False(t, initialized)
322322

323323
crw := &cosiapi.BucketClaim{}
324324
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -371,10 +371,10 @@ func TestBucketAccessReconcile(t *testing.T) {
371371
assert.Empty(t, status.AuthenticationType)
372372
assert.Empty(t, status.Parameters)
373373

374-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
375-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
374+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
375+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
376376
assert.NoError(t, err)
377-
assert.True(t, needInit)
377+
assert.False(t, initialized)
378378

379379
crw := &cosiapi.BucketClaim{}
380380
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -424,10 +424,10 @@ func TestBucketAccessReconcile(t *testing.T) {
424424
assert.Empty(t, status.AuthenticationType)
425425
assert.Empty(t, status.Parameters)
426426

427-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
428-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
427+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
428+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
429429
assert.NoError(t, err)
430-
assert.True(t, needInit)
430+
assert.False(t, initialized)
431431

432432
crw := &cosiapi.BucketClaim{}
433433
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -474,10 +474,10 @@ func TestBucketAccessReconcile(t *testing.T) {
474474
assert.Empty(t, status.AuthenticationType)
475475
assert.Empty(t, status.Parameters)
476476

477-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
478-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
477+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
478+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
479479
assert.NoError(t, err)
480-
assert.True(t, needInit)
480+
assert.False(t, initialized)
481481

482482
crw := &cosiapi.BucketClaim{}
483483
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -526,10 +526,10 @@ func TestBucketAccessReconcile(t *testing.T) {
526526
assert.Empty(t, status.AuthenticationType)
527527
assert.Empty(t, status.Parameters)
528528

529-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
530-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
529+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
530+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
531531
assert.NoError(t, err)
532-
assert.True(t, needInit)
532+
assert.False(t, initialized)
533533

534534
crw := &cosiapi.BucketClaim{}
535535
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -594,10 +594,10 @@ func TestBucketAccessReconcile(t *testing.T) {
594594
status.Parameters,
595595
)
596596

597-
assert.True(t, handoff.BucketAccessManagedBySidecar(access)) // MUST hand off to sidecar
598-
needInit, err := needsControllerInitialization(&access.Status) // MUST be fully initialized
597+
assert.True(t, bucketaccess.ManagedBySidecar(access)) // MUST hand off to sidecar
598+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST be fully initialized
599599
assert.NoError(t, err)
600-
assert.False(t, needInit)
600+
assert.True(t, initialized)
601601

602602
crw := &cosiapi.BucketClaim{}
603603
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -650,10 +650,10 @@ func TestBucketAccessReconcile(t *testing.T) {
650650
assert.Empty(t, status.AuthenticationType)
651651
assert.Empty(t, status.Parameters)
652652

653-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
654-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
653+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
654+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
655655
assert.NoError(t, err)
656-
assert.True(t, needInit)
656+
assert.False(t, initialized)
657657

658658
crw := &cosiapi.BucketClaim{}
659659
err = c.Get(ctx, readWriteClaimNsName, crw)
@@ -706,10 +706,10 @@ func TestBucketAccessReconcile(t *testing.T) {
706706
assert.Empty(t, status.AuthenticationType)
707707
assert.Empty(t, status.Parameters)
708708

709-
assert.False(t, handoff.BucketAccessManagedBySidecar(access)) // MUST NOT hand off to sidecar
710-
needInit, err := needsControllerInitialization(&access.Status) // MUST NOT be initialized
709+
assert.False(t, bucketaccess.ManagedBySidecar(access)) // MUST NOT hand off to sidecar
710+
initialized, err := bucketaccess.SidecarRequirementsPresent(&access.Status) // MUST NOT be initialized
711711
assert.NoError(t, err)
712-
assert.True(t, needInit)
712+
assert.False(t, initialized)
713713

714714
crw := &cosiapi.BucketClaim{}
715715
err = c.Get(ctx, readWriteClaimNsName, crw)

go.mod

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ require (
1313
github.com/go-logr/logr v1.4.3
1414
github.com/stretchr/testify v1.11.1
1515
google.golang.org/grpc v1.75.1
16+
k8s.io/api v0.34.3
1617
k8s.io/apimachinery v0.34.3
17-
k8s.io/client-go v0.34.3
18+
k8s.io/client-go v0.34.2
1819
k8s.io/utils v0.0.0-20250820121507-0af2bda4dd1d
1920
sigs.k8s.io/container-object-storage-interface/client v0.0.0-20250925174816-5fce7c365e9c
2021
sigs.k8s.io/container-object-storage-interface/proto v0.0.0-00010101000000-000000000000
@@ -23,89 +24,80 @@ require (
2324

2425
require (
2526
cel.dev/expr v0.24.0 // indirect
26-
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
27+
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
2728
github.com/beorn7/perks v1.0.1 // indirect
2829
github.com/blang/semver/v4 v4.0.0 // indirect
29-
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
30+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
3031
github.com/cespare/xxhash/v2 v2.3.0 // indirect
31-
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
32-
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
32+
github.com/davecgh/go-spew v1.1.1 // indirect
33+
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
3334
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
3435
github.com/felixge/httpsnoop v1.0.4 // indirect
3536
github.com/fsnotify/fsnotify v1.9.0 // indirect
3637
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
3738
github.com/go-logr/stdr v1.2.2 // indirect
3839
github.com/go-logr/zapr v1.3.0 // indirect
39-
github.com/go-openapi/jsonpointer v0.22.0 // indirect
40-
github.com/go-openapi/jsonreference v0.21.1 // indirect
41-
github.com/go-openapi/swag v0.25.1 // indirect
42-
github.com/go-openapi/swag/cmdutils v0.25.1 // indirect
43-
github.com/go-openapi/swag/conv v0.25.1 // indirect
44-
github.com/go-openapi/swag/fileutils v0.25.1 // indirect
45-
github.com/go-openapi/swag/jsonname v0.25.1 // indirect
46-
github.com/go-openapi/swag/jsonutils v0.25.1 // indirect
47-
github.com/go-openapi/swag/loading v0.25.1 // indirect
48-
github.com/go-openapi/swag/mangling v0.25.1 // indirect
49-
github.com/go-openapi/swag/netutils v0.25.1 // indirect
50-
github.com/go-openapi/swag/stringutils v0.25.1 // indirect
51-
github.com/go-openapi/swag/typeutils v0.25.1 // indirect
52-
github.com/go-openapi/swag/yamlutils v0.25.1 // indirect
40+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
41+
github.com/go-openapi/jsonreference v0.20.2 // indirect
42+
github.com/go-openapi/swag v0.23.0 // indirect
5343
github.com/gogo/protobuf v1.3.2 // indirect
5444
github.com/google/btree v1.1.3 // indirect
55-
github.com/google/cel-go v0.26.1 // indirect
45+
github.com/google/cel-go v0.26.0 // indirect
5646
github.com/google/gnostic-models v0.7.0 // indirect
5747
github.com/google/go-cmp v0.7.0 // indirect
5848
github.com/google/uuid v1.6.0 // indirect
59-
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
49+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
6050
github.com/inconshreveable/mousetrap v1.1.0 // indirect
51+
github.com/josharian/intern v1.0.0 // indirect
6152
github.com/json-iterator/go v1.1.12 // indirect
53+
github.com/mailru/easyjson v0.7.7 // indirect
6254
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
6355
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
6456
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
57+
github.com/pkg/errors v0.9.1 // indirect
6558
github.com/pmezard/go-difflib v1.0.0 // indirect
66-
github.com/prometheus/client_golang v1.23.2 // indirect
67-
github.com/prometheus/client_model v0.6.2 // indirect
68-
github.com/prometheus/common v0.66.1 // indirect
69-
github.com/prometheus/procfs v0.17.0 // indirect
70-
github.com/spf13/cobra v1.10.1 // indirect
71-
github.com/spf13/pflag v1.0.10 // indirect
72-
github.com/stoewer/go-strcase v1.3.1 // indirect
59+
github.com/prometheus/client_golang v1.22.0 // indirect
60+
github.com/prometheus/client_model v0.6.1 // indirect
61+
github.com/prometheus/common v0.62.0 // indirect
62+
github.com/prometheus/procfs v0.15.1 // indirect
63+
github.com/spf13/cobra v1.9.1 // indirect
64+
github.com/spf13/pflag v1.0.6 // indirect
65+
github.com/stoewer/go-strcase v1.3.0 // indirect
7366
github.com/x448/float16 v0.8.4 // indirect
74-
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
75-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
76-
go.opentelemetry.io/otel v1.38.0 // indirect
77-
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
78-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
79-
go.opentelemetry.io/otel/metric v1.38.0 // indirect
80-
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
81-
go.opentelemetry.io/otel/trace v1.38.0 // indirect
82-
go.opentelemetry.io/proto/otlp v1.8.0 // indirect
67+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
68+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
69+
go.opentelemetry.io/otel v1.37.0 // indirect
70+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
71+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
72+
go.opentelemetry.io/otel/metric v1.37.0 // indirect
73+
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
74+
go.opentelemetry.io/otel/trace v1.37.0 // indirect
75+
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
8376
go.uber.org/multierr v1.11.0 // indirect
8477
go.uber.org/zap v1.27.0 // indirect
8578
go.yaml.in/yaml/v2 v2.4.3 // indirect
8679
go.yaml.in/yaml/v3 v3.0.4 // indirect
87-
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
80+
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
8881
golang.org/x/net v0.44.0 // indirect
89-
golang.org/x/oauth2 v0.31.0 // indirect
82+
golang.org/x/oauth2 v0.30.0 // indirect
9083
golang.org/x/sync v0.17.0 // indirect
9184
golang.org/x/sys v0.36.0 // indirect
9285
golang.org/x/term v0.35.0 // indirect
9386
golang.org/x/text v0.29.0 // indirect
94-
golang.org/x/time v0.13.0 // indirect
95-
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
96-
google.golang.org/genproto/googleapis/api v0.0.0-20250922171735-9219d122eba9 // indirect
87+
golang.org/x/time v0.9.0 // indirect
88+
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
89+
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
9790
google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect
9891
google.golang.org/protobuf v1.36.9 // indirect
99-
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
92+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
10093
gopkg.in/inf.v0 v0.9.1 // indirect
10194
gopkg.in/yaml.v3 v3.0.1 // indirect
102-
k8s.io/api v0.34.3 // indirect
103-
k8s.io/apiextensions-apiserver v0.34.1 // indirect
104-
k8s.io/apiserver v0.34.1 // indirect
105-
k8s.io/component-base v0.34.1 // indirect
95+
k8s.io/apiextensions-apiserver v0.34.0 // indirect
96+
k8s.io/apiserver v0.34.0 // indirect
97+
k8s.io/component-base v0.34.0 // indirect
10698
k8s.io/klog/v2 v2.130.1 // indirect
107-
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
108-
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 // indirect
99+
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
100+
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 // indirect
109101
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
110102
sigs.k8s.io/randfill v1.0.0 // indirect
111103
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect

0 commit comments

Comments
 (0)