Skip to content

Commit d587b32

Browse files
committed
add initial BucketClaim controller reconciliation
Add initial implementation for BucketClaim reconciliation based on v1alpha2 KEP. This initial implementation covers only the first section of Controller reconciliation for a new BucketClaim. Coverage ends at the point where reconciliation is handed off to the Sidecar. Signed-off-by: Blaine Gardner <[email protected]>
1 parent a78a0e6 commit d587b32

Some content is hidden

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

55 files changed

+8459
-452
lines changed

.golangci.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ issues:
1616
linters:
1717
- dupl
1818
- lll
19+
- path: "_test.go"
20+
linters:
21+
- goconst
22+
1923
linters:
2024
disable-all: true
2125
enable:

client/apis/objectstorage/v1alpha2/bucket_types.go

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,81 @@ package v1alpha2
1818

1919
import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
"k8s.io/apimachinery/pkg/types"
2122
)
2223

23-
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24-
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
24+
// BucketDeletionPolicy configures COSI's behavior when a Bucket resource is deleted.
25+
// +enum
26+
// +kubebuilder:validation:Enum:=Retain;Delete
27+
type BucketDeletionPolicy string
28+
29+
const (
30+
// BucketDeletionPolicyRetain configures COSI to keep the Bucket object as well as the backend
31+
// bucket when a Bucket resource is deleted.
32+
BucketDeletionPolicyRetain BucketDeletionPolicy = "Retain"
33+
34+
// BucketDeletionPolicyDelete configures COSI to delete the Bucket object as well as the backend
35+
// bucket when a Bucket resource is deleted.
36+
BucketDeletionPolicyDelete BucketDeletionPolicy = "Delete"
37+
)
2538

2639
// BucketSpec defines the desired state of Bucket
2740
type BucketSpec struct {
28-
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29-
// Important: Run "make" to regenerate code after modifying this file
30-
// The following markers will use OpenAPI v3 schema to validate the value
31-
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
41+
// driverName is the name of the driver that fulfills requests for this Bucket.
42+
// +required
43+
// +kubebuilder:validation:MinLength=1
44+
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="self == oldSelf"
45+
DriverName string `json:"driverName"`
46+
47+
// deletionPolicy determines whether a Bucket should be deleted when its bound BucketClaim is
48+
// deleted. This is mutable to allow Admins to change the policy after creation.
49+
// Possible values:
50+
// - Retain: keep both the Bucket object and the backend bucket
51+
// - Delete: delete both the Bucket object and the backend bucket
52+
// +required
53+
DeletionPolicy BucketDeletionPolicy `json:"deletionPolicy"`
54+
55+
// parameters is an opaque map of driver-specific configuration items passed to the driver that
56+
// fulfills requests for this Bucket.
57+
// +optional
58+
// +kubebuilder:validation:XValidation:message="parameters map is immutable",rule="self == oldSelf"
59+
Parameters map[string]string `json:"parameters,omitempty"`
60+
61+
// protocols lists object store protocols that the provisioned Bucket must support.
62+
// If specified, COSI will verify that each item is advertised as supported by the driver.
63+
// +optional
64+
// +listType=set
65+
// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="self == oldSelf"
66+
Protocols []ObjectProtocol `json:"protocols,omitempty"`
67+
68+
// bucketClaim references the BucketClaim that resulted in the creation of this Bucket.
69+
// For statically-provisioned buckets, set the namespace and name of the BucketClaim that is
70+
// allowed to bind to this Bucket.
71+
// +required
72+
BucketClaimRef BucketClaimReference `json:"bucketClaim"`
73+
}
74+
75+
// BucketClaimReference is a reference to a BucketClaim object.
76+
type BucketClaimReference struct {
77+
// name is the name of the BucketClaim being referenced.
78+
// +required
79+
// +kubebuilder:validation:MinLength=1
80+
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="self == oldSelf"
81+
Name string `json:"name"`
82+
83+
// namespace is the namespace of the BucketClaim being referenced.
84+
// If empty, the Kubernetes 'default' namespace is assumed.
85+
// namespace is immutable except to update '' to 'default'.
86+
// +optional
87+
// +kubebuilder:validation:MinLength=0
88+
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="(oldSelf == '' && self == 'default') || self == oldSelf"
89+
Namespace string `json:"namespace"`
3290

33-
// foo is an example field of Bucket. Edit bucket_types.go to remove/update
91+
// uid is the UID of the BucketClaim being referenced.
92+
// Once set, the UID is immutable.
3493
// +optional
35-
Foo *string `json:"foo,omitempty"`
94+
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="oldSelf == '' || self == oldSelf"
95+
UID types.UID `json:"uid"`
3696
}
3797

3898
// BucketStatus defines the observed state of Bucket.
@@ -46,6 +106,8 @@ type BucketStatus struct {
46106

47107
// +kubebuilder:object:root=true
48108
// +kubebuilder:subresource:status
109+
// +kubebuilder:resource:scope=Cluster
110+
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes"
49111

50112
// Bucket is the Schema for the buckets API
51113
type Bucket struct {

client/apis/objectstorage/v1alpha2/bucketaccess_types.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
)
2222

23-
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24-
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
25-
2623
// BucketAccessSpec defines the desired state of BucketAccess
2724
type BucketAccessSpec struct {
2825
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
@@ -60,6 +57,7 @@ type BucketAccessStatus struct {
6057

6158
// +kubebuilder:object:root=true
6259
// +kubebuilder:subresource:status
60+
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes"
6361

6462
// BucketAccess is the Schema for the bucketaccesses API
6563
type BucketAccess struct {

client/apis/objectstorage/v1alpha2/bucketaccessclass_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ type BucketAccessClassStatus struct {
6060

6161
// +kubebuilder:object:root=true
6262
// +kubebuilder:subresource:status
63+
// +kubebuilder:resource:scope=Cluster
64+
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes"
6365

6466
// BucketAccessClass is the Schema for the bucketaccessclasses API
6567
type BucketAccessClass struct {

client/apis/objectstorage/v1alpha2/bucketclaim_types.go

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,46 +20,56 @@ import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
)
2222

23-
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24-
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
25-
2623
// BucketClaimSpec defines the desired state of BucketClaim
24+
// +kubebuilder:validation:ExactlyOneOf=bucketClassName;existingBucketName
2725
type BucketClaimSpec struct {
28-
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29-
// Important: Run "make" to regenerate code after modifying this file
30-
// The following markers will use OpenAPI v3 schema to validate the value
31-
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
26+
// bucketClassName selects the BucketClass for provisioning the BucketClaim.
27+
// This field is used only for BucketClaim dynamic provisioning.
28+
// If unspecified, existingBucketName must be specified for binding to an existing Bucket.
29+
// +optional
30+
// +kubebuilder:validation:XValidation:message="bucketClassName is immutable",rule="self == oldSelf"
31+
BucketClassName string `json:"bucketClassName,omitempty"`
32+
33+
// protocols lists object storage protocols that the provisioned Bucket must support.
34+
// If specified, COSI will verify that each item is advertised as supported by the driver.
35+
// +optional
36+
// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="self == oldSelf"
37+
Protocols []ObjectProtocol `json:"protocols,omitempty"`
3238

33-
// foo is an example field of BucketClaim. Edit bucketclaim_types.go to remove/update
39+
// existingBucketName selects the name of an existing Bucket resource that this BucketClaim
40+
// should bind to.
41+
// This field is used only for BucketClaim static provisioning.
42+
// If unspecified, bucketClassName must be specified for dynamically provisioning a new bucket.
3443
// +optional
35-
Foo *string `json:"foo,omitempty"`
44+
// +kubebuilder:validation:XValidation:message="existingBucketName is immutable",rule="self == oldSelf"
45+
ExistingBucketName string `json:"existingBucketName,omitempty"`
3646
}
3747

3848
// BucketClaimStatus defines the observed state of BucketClaim.
3949
type BucketClaimStatus struct {
40-
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
41-
// Important: Run "make" to regenerate code after modifying this file
42-
43-
// For Kubernetes API conventions, see:
44-
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
45-
46-
// conditions represent the current state of the BucketClaim resource.
47-
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
48-
//
49-
// Standard condition types include:
50-
// - "Available": the resource is fully functional
51-
// - "Progressing": the resource is being created or updated
52-
// - "Degraded": the resource failed to reach or maintain its desired state
53-
//
54-
// The status of each condition is one of True, False, or Unknown.
55-
// +listType=map
56-
// +listMapKey=type
50+
// boundBucketName is the name of the Bucket this BucketClaim is bound to.
51+
// Once set, this is immutable.
52+
// +kubebuilder:validation:XValidation:message="boundBucketName is immutable",rule="oldSelf == '' || self == oldSelf"
53+
BoundBucketName string `json:"boundBucketName"`
54+
55+
// readyToUse indicates that the bucket is ready for consumption by workloads.
56+
ReadyToUse bool `json:"readyToUse"`
57+
58+
// protocols is the set of protocols the bound Bucket reports to support. BucketAccesses can
59+
// request access to this BucketClaim using any of the protocols reported here.
60+
// +optional
61+
// +listType=set
62+
Protocols []ObjectProtocol `json:"protocols"`
63+
64+
// error holds the most recent error message, with a timestamp.
65+
// This is cleared when provisioning is successful.
5766
// +optional
58-
Conditions []metav1.Condition `json:"conditions,omitempty"`
67+
Error *TimestampedError `json:"error,omitempty"`
5968
}
6069

6170
// +kubebuilder:object:root=true
6271
// +kubebuilder:subresource:status
72+
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes"
6373

6474
// BucketClaim is the Schema for the bucketclaims API
6575
type BucketClaim struct {

client/apis/objectstorage/v1alpha2/bucketclass_types.go

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -20,62 +20,46 @@ import (
2020
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2121
)
2222

23-
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24-
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
25-
26-
// BucketClassSpec defines the desired state of BucketClass
23+
// BucketClassSpec defines the BucketClass.
2724
type BucketClassSpec struct {
28-
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29-
// Important: Run "make" to regenerate code after modifying this file
30-
// The following markers will use OpenAPI v3 schema to validate the value
31-
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
32-
33-
// foo is an example field of BucketClass. Edit bucketclass_types.go to remove/update
34-
// +optional
35-
Foo *string `json:"foo,omitempty"`
36-
}
37-
38-
// BucketClassStatus defines the observed state of BucketClass.
39-
type BucketClassStatus struct {
40-
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
41-
// Important: Run "make" to regenerate code after modifying this file
42-
43-
// For Kubernetes API conventions, see:
44-
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
25+
// driverName is the name of the driver that fulfills requests for this BucketClass.
26+
// +required
27+
// +kubebuilder:validation:MinLength=1
28+
DriverName string `json:"driverName"`
29+
30+
// deletionPolicy determines whether a Bucket created through the BucketClass should be deleted
31+
// when its bound BucketClaim is deleted.
32+
// Possible values:
33+
// - Retain: keep both the Bucket object and the backend bucket
34+
// - Delete: delete both the Bucket object and the backend bucket
35+
// +required
36+
DeletionPolicy BucketDeletionPolicy `json:"deletionPolicy"`
4537

46-
// conditions represent the current state of the BucketClass resource.
47-
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
48-
//
49-
// Standard condition types include:
50-
// - "Available": the resource is fully functional
51-
// - "Progressing": the resource is being created or updated
52-
// - "Degraded": the resource failed to reach or maintain its desired state
53-
//
54-
// The status of each condition is one of True, False, or Unknown.
55-
// +listType=map
56-
// +listMapKey=type
38+
// parameters is an opaque map of driver-specific configuration items passed to the driver that
39+
// fulfills requests for this BucketClass.
5740
// +optional
58-
Conditions []metav1.Condition `json:"conditions,omitempty"`
41+
Parameters map[string]string `json:"parameters,omitempty"`
5942
}
6043

6144
// +kubebuilder:object:root=true
62-
// +kubebuilder:subresource:status
45+
// +kubebuilder:resource:scope=Cluster
46+
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes"
6347

64-
// BucketClass is the Schema for the bucketclasses API
48+
// BucketClass defines a named "class" of object storage buckets.
49+
// Different classes might map to different object storage protocols, quality-of-service levels,
50+
// backup policies, or any other arbitrary configuration determined by storage administrators.
51+
// The name of a BucketClass object is significant, and is how users can request a particular class.
6552
type BucketClass struct {
6653
metav1.TypeMeta `json:",inline"`
6754

6855
// metadata is a standard object metadata
6956
// +optional
7057
metav1.ObjectMeta `json:"metadata,omitempty,omitzero"`
7158

72-
// spec defines the desired state of BucketClass
59+
// spec defines the BucketClass. spec is entirely immutable.
7360
// +required
61+
// +kubebuilder:validation:XValidation:message="BucketClass spec is immutable",rule="self == oldSelf"
7462
Spec BucketClassSpec `json:"spec"`
75-
76-
// status defines the observed state of BucketClass
77-
// +optional
78-
Status BucketClassStatus `json:"status,omitempty,omitzero"`
7963
}
8064

8165
// +kubebuilder:object:root=true

client/apis/objectstorage/v1alpha2/definitions.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ limitations under the License.
1616

1717
package v1alpha2
1818

19+
const (
20+
// ProtectionFinalizer is applied to a COSI resource object to protect it from deletion while
21+
// COSI processes deletion of the object's intermediate and backend resources.
22+
ProtectionFinalizer = `objectstorage.k8s.io/protection`
23+
)
24+
1925
const (
2026
// RpcEndpointDefault is the default RPC endpoint unix socket location.
2127
RpcEndpointDefault = "unix:///var/lib/cosi/cosi.sock"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha2
18+
19+
/*
20+
This file contains all definitions for the various object store protocols.
21+
*/
22+
23+
// ObjectProtocol represents an object protocol type.
24+
type ObjectProtocol string
25+
26+
const (
27+
// ObjectProtocolS3 represents the S3 object protocol type.
28+
ObjectProtocolS3 = "S3"
29+
30+
// ObjectProtocolS3 represents the Azure Blob object protocol type.
31+
ObjectProtocolAzure = "Azure"
32+
33+
// ObjectProtocolS3 represents the Google Cloud Storage object protocol type.
34+
ObjectProtocolGcs = "GCS"
35+
)

0 commit comments

Comments
 (0)