Skip to content

Commit 811da8f

Browse files
committed
add bucketaccess(class) types, and tidy all CEL rules
Add Kubernetes API (client) types for BucketAccess and BucketAccessClass. Since these are the last API types, also standardize CEL rule invocations for existing types. Signed-off-by: Blaine Gardner <[email protected]>
1 parent 6fe2318 commit 811da8f

17 files changed

+920
-348
lines changed

client/apis/objectstorage/v1alpha2/bucket_types.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ const (
3737
)
3838

3939
// BucketSpec defines the desired state of Bucket
40+
// +kubebuilder:validation:XValidation:message="parameters map is immutable",rule="has(oldSelf.parameters) == has(self.parameters)"
41+
// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="has(oldSelf.protocols) == has(self.protocols)"
42+
// +kubebuilder:validation:XValidation:message="existingBucketID is immutable",rule="has(oldSelf.existingBucketID) == has(self.existingBucketID)"
4043
type BucketSpec struct {
4144
// driverName is the name of the driver that fulfills requests for this Bucket.
4245
// +required
@@ -81,36 +84,41 @@ type BucketSpec struct {
8184
}
8285

8386
// BucketClaimReference is a reference to a BucketClaim object.
87+
// +kubebuilder:validation:XValidation:message="namespace is immutable once set",rule="!has(oldSelf.namespace) || has(self.namespace)"
88+
// +kubebuilder:validation:XValidation:message="uid is immutable once set",rule="!has(oldSelf.uid) || has(self.uid)"
8489
type BucketClaimReference struct {
8590
// name is the name of the BucketClaim being referenced.
8691
// +required
8792
// +kubebuilder:validation:MinLength=1
88-
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="self == oldSelf"
93+
// +kubebuilder:validation:MaxLength=253
94+
// +kubebuilder:validation:XValidation:message="name is immutable",rule="self == oldSelf"
8995
Name string `json:"name"`
9096

9197
// namespace is the namespace of the BucketClaim being referenced.
9298
// If empty, the Kubernetes 'default' namespace is assumed.
9399
// namespace is immutable except to update '' to 'default'.
94100
// +optional
95101
// +kubebuilder:validation:MinLength=0
96-
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="(oldSelf == '' && self == 'default') || self == oldSelf"
102+
// +kubebuilder:validation:MaxLength=253
103+
// +kubebuilder:validation:XValidation:message="namespace is immutable",rule="(oldSelf == '' && self == 'default') || self == oldSelf"
97104
Namespace string `json:"namespace"`
98105

99106
// uid is the UID of the BucketClaim being referenced.
100-
// Once set, the UID is immutable.
101107
// +optional
102-
// +kubebuilder:validation:XValidation:message="driverName is immutable",rule="oldSelf == '' || self == oldSelf"
108+
// +kubebuilder:validation:XValidation:message="uid is immutable once set",rule="oldSelf == '' || self == oldSelf"
103109
UID types.UID `json:"uid"`
104110
}
105111

106112
// BucketStatus defines the observed state of Bucket.
113+
// +kubebuilder:validation:XValidation:message="bucketID is immutable once set",rule="!has(oldSelf.bucketID) || has(self.bucketID)"
114+
// +kubebuilder:validation:XValidation:message="protocols is immutable once set",rule="!has(oldSelf.protocols) || has(self.protocols)"
107115
type BucketStatus struct {
108116
// readyToUse indicates that the bucket is ready for consumption by workloads.
109117
ReadyToUse bool `json:"readyToUse"`
110118

111119
// bucketID is the unique identifier for the backend bucket known to the driver.
112-
// Once set, this is immutable.
113-
// +kubebuilder:validation:XValidation:message="boundBucketName is immutable",rule="oldSelf == '' || self == oldSelf"
120+
// +optional
121+
// +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="oldSelf == '' || self == oldSelf"
114122
BucketID string `json:"bucketID"`
115123

116124
// protocols is the set of protocols the Bucket reports to support. BucketAccesses can request

client/apis/objectstorage/v1alpha2/bucketaccess_types.go

Lines changed: 135 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import (
2222

2323
// BucketAccessAuthenticationType specifies what authentication mechanism is used for provisioning
2424
// bucket access.
25+
// +enum
26+
// +kubebuilder:validation:Enum:="";Key;ServiceAccount
2527
type BucketAccessAuthenticationType string
2628

2729
const (
28-
// The driver will generate a protocol-appropriate access key that clients can use to
30+
// The driver should generate a protocol-appropriate access key that clients can use to
2931
// authenticate to the backend object store.
3032
BucketAccessAuthenticationTypeKey = "Key"
3133

@@ -34,39 +36,148 @@ const (
3436
BucketAccessAuthenticationTypeServiceAccount = "ServiceAccount"
3537
)
3638

39+
// BucketAccessMode describes the Read/Write mode an access should have for a bucket.
40+
// +enum
41+
// +kubebuilder:validation:Enum:=ReadWrite;ReadOnly;WriteOnly
42+
type BucketAccessMode string
43+
44+
const (
45+
// BucketAccessModeReadWrite represents read-write access mode.
46+
BucketAccessModeReadWrite BucketAccessMode = "ReadWrite"
47+
48+
// BucketAccessModeReadOnly represents read-only access mode.
49+
BucketAccessModeReadOnly BucketAccessMode = "ReadOnly"
50+
51+
// BucketAccessModeWriteOnly represents write-only access mode.
52+
BucketAccessModeWriteOnly BucketAccessMode = "WriteOnly"
53+
)
54+
3755
// BucketAccessSpec defines the desired state of BucketAccess
56+
// +kubebuilder:validation:XValidation:message="serviceAccountName is immutable",rule="has(oldSelf.serviceAccountName) == has(self.serviceAccountName)"
3857
type BucketAccessSpec struct {
39-
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
40-
// Important: Run "make" to regenerate code after modifying this file
41-
// The following markers will use OpenAPI v3 schema to validate the value
42-
// More info: https://book.kubebuilder.io/reference/markers/crd-validation.html
58+
// bucketClaims is a list of BucketClaims the provisioned access must have permissions for,
59+
// along with per-BucketClaim access parameters and system output definitions.
60+
// At least one BucketClaim must be referenced.
61+
// Multiple references to the same BucketClaim are not permitted.
62+
// +required
63+
// +listType=map
64+
// +listMapKey=bucketClaimName
65+
// +kubebuilder:validation:MinItems=1
66+
// +kubebuilder:validation:XValidation:message="bucketClaims list is immutable",rule="self == oldSelf"
67+
BucketClaims []BucketClaimAccess `json:"bucketClaims"`
4368

44-
// foo is an example field of BucketAccess. Edit bucketaccess_types.go to remove/update
69+
// bucketAccessClassName selects the BucketAccessClass for provisioning the access.
70+
// +required
71+
// +kubebuilder:validation:MinLength=1
72+
// +kubebuilder:validation:MaxLength=253
73+
// +kubebuilder:validation:XValidation:message="bucketAccessClassName is immutable",rule="self == oldSelf"
74+
BucketAccessClassName string `json:"bucketAccessClassName"`
75+
76+
// protocol is the object storage protocol that the provisioned access must use.
77+
// +required
78+
// +kubebuilder:validation:XValidation:message="protocol is immutable",rule="self == oldSelf"
79+
Protocol ObjectProtocol `json:"protocol"`
80+
81+
// serviceAccountName is the name of the Kubernetes ServiceAccount that user application Pods
82+
// intend to use for access to referenced BucketClaims.
83+
// This has different behavior based on the BucketAccessClass's defined AuthenticationType:
84+
// - Key: This field is ignored.
85+
// - ServiceAccount: This field is required. The driver should configure the system so that Pods
86+
// using the ServiceAccount authenticate to the object storage backend automatically.
4587
// +optional
46-
Foo *string `json:"foo,omitempty"`
88+
// +kubebuilder:validation:MaxLength=253
89+
// +kubebuilder:validation:XValidation:message="serviceAccountName is immutable",rule="self == oldSelf"
90+
ServiceAccountName string `json:"serviceAccountName,omitempty"`
4791
}
4892

4993
// BucketAccessStatus defines the observed state of BucketAccess.
94+
// +kubebuilder:validation:XValidation:message="accountID is immutable once set",rule="!has(oldSelf.accountID) || has(self.accountID)"
95+
// +kubebuilder:validation:XValidation:message="accessedBuckets is immutable once set",rule="!has(oldSelf.accessedBuckets) || has(self.accessedBuckets)"
96+
// +kubebuilder:validation:XValidation:message="driverName is immutable once set",rule="!has(oldSelf.driverName) || has(self.driverName)"
97+
// +kubebuilder:validation:XValidation:message="authenticationType is immutable once set",rule="!has(oldSelf.authenticationType) || has(self.authenticationType)"
98+
// +kubebuilder:validation:XValidation:message="parameters is immutable once set",rule="!has(oldSelf.parameters) || has(self.parameters)"
5099
type BucketAccessStatus struct {
51-
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
52-
// Important: Run "make" to regenerate code after modifying this file
53-
54-
// For Kubernetes API conventions, see:
55-
// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties
56-
57-
// conditions represent the current state of the BucketAccess resource.
58-
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
59-
//
60-
// Standard condition types include:
61-
// - "Available": the resource is fully functional
62-
// - "Progressing": the resource is being created or updated
63-
// - "Degraded": the resource failed to reach or maintain its desired state
64-
//
65-
// The status of each condition is one of True, False, or Unknown.
100+
// readyToUse indicates that the BucketAccess is ready for consumption by workloads.
101+
ReadyToUse bool `json:"readyToUse"`
102+
103+
// accountID is the unique identifier for the backend access known to the driver.
104+
// This field is populated by the COSI Sidecar once access has been successfully granted.
105+
// +optional
106+
// +kubebuilder:validation:XValidation:message="accountId is immutable once set",rule="oldSelf == '' || self == oldSelf"
107+
AccountID string `json:"accountID"`
108+
109+
// accessedBuckets is a list of Buckets the provisioned access must have permissions for, along
110+
// with per-Bucket access options. This field is populated by the COSI Controller based on the
111+
// referenced BucketClaims in the spec.
112+
// +optional
66113
// +listType=map
67-
// +listMapKey=type
114+
// +listMapKey=bucketName
115+
// +kubebuilder:validation:XValidation:message="accessedBuckets is immutable once set",rule="oldSelf.size() == 0 || self == oldSelf"
116+
AccessedBuckets []AccessedBucket `json:"accessedBuckets"`
117+
118+
// driverName holds a copy of the BucketAccessClass driver name from the time of BucketAccess
119+
// provisioning. This field is populated by the COSI Controller.
68120
// +optional
69-
Conditions []metav1.Condition `json:"conditions,omitempty"`
121+
// +kubebuilder:validation:XValidation:message="driverName is immutable once set",rule="oldSelf == '' || self == oldSelf"
122+
DriverName string `json:"driverName"`
123+
124+
// authenticationType holds a copy of the BucketAccessClass authentication type from the time of
125+
// BucketAccess provisioning. This field is populated by the COSI Controller.
126+
// +optional
127+
// +kubebuilder:validation:XValidation:message="authenticationType is immutable once set",rule="oldSelf == '' || self == oldSelf"
128+
AuthenticationType BucketAccessAuthenticationType `json:"authenticationType"`
129+
130+
// parameters holds a copy of the BucketAccessClass parameters from the time of BucketAccess
131+
// provisioning. This field is populated by the COSI Controller.
132+
// +optional
133+
// +kubebuilder:validation:XValidation:message="accessedBuckets is immutable once set",rule="oldSelf.size() == 0 || self == oldSelf"
134+
Parameters map[string]string `json:"parameters,omitempty"`
135+
136+
// error holds the most recent error message, with a timestamp.
137+
// This is cleared when provisioning is successful.
138+
// +optional
139+
Error *TimestampedError `json:"error,omitempty"`
140+
}
141+
142+
// BucketClaimAccess selects a BucketClaim for access, defines access parameters for the
143+
// corresponding bucket, and specifies where user-consumable bucket information and access
144+
// credentials for the accessed bucket will be stored.
145+
type BucketClaimAccess struct {
146+
// bucketClaimName is the name of a BucketClaim the access should have permissions for.
147+
// The BucketClaim must be in the same Namespace as the BucketAccess.
148+
// +required
149+
// +kubebuilder:validation:MinLength=1
150+
// +kubebuilder:validation:MaxLength=253
151+
BucketClaimName string `json:"bucketClaimName"`
152+
153+
// accessMode is the Read/Write access mode that the access should have for the bucket.
154+
// Possible values: ReadWrite, ReadOnly, WriteOnly.
155+
// +required
156+
AccessMode BucketAccessMode `json:"accessMode"`
157+
158+
// accessSecretName is the name of a Kubernetes Secret that COSI should create and populate with
159+
// bucket info and access credentials for the bucket.
160+
// The Secret is created in the same Namespace as the BucketAccess and is deleted when the
161+
// BucketAccess is deleted and deprovisioned.
162+
// The Secret name must be unique across all bucketClaimRefs for all BucketAccesses in the same
163+
// Namespace.
164+
// +required
165+
// +kubebuilder:validation:MinLength=1
166+
// +kubebuilder:validation:MaxLength=253
167+
AccessSecretName string `json:"accessSecretName"`
168+
}
169+
170+
// AccessedBucket identifies a Bucket and corresponding access parameters.
171+
type AccessedBucket struct {
172+
// bucketName is the name of a Bucket the access should have permissions for.
173+
// +required
174+
// +kubebuilder:validation:MinLength=1
175+
// +kubebuilder:validation:MaxLength=253
176+
BucketName string `json:"bucketName"`
177+
178+
// accessMode is the Read/Write access mode that the access should have for the bucket.
179+
// +required
180+
AccessMode BucketAccessMode `json:"accessMode"`
70181
}
71182

72183
// +kubebuilder:object:root=true

client/apis/objectstorage/v1alpha2/bucketaccessclass_types.go

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,42 +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-
2623
// BucketAccessClassSpec defines the desired state of BucketAccessClass
2724
type BucketAccessClassSpec 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
25+
// driverName is the name of the driver that fulfills requests for this BucketAccessClass.
26+
// +required
27+
// +kubebuilder:validation:MinLength=1
28+
DriverName string `json:"driverName"`
29+
30+
// authenticationType specifies which authentication mechanism is used bucket access.
31+
// Possible values:
32+
// - Key: The driver should generate a protocol-appropriate access key that clients can use to
33+
// authenticate to the backend object store.
34+
// - ServiceAccount: The driver should configure the system such that Pods using the given
35+
// ServiceAccount authenticate to the backend object store automatically.
36+
// +required
37+
// +kubebuilder:validation:Enum:=Key;ServiceAccount
38+
AuthenticationType BucketAccessAuthenticationType `json:"authenticationType"`
39+
40+
// parameters is an opaque map of driver-specific configuration items passed to the driver that
41+
// fulfills requests for this BucketAccessClass.
42+
// +optional
43+
Parameters map[string]string `json:"parameters,omitempty"`
3244

33-
// foo is an example field of BucketAccessClass. Edit bucketaccessclass_types.go to remove/update
45+
// featureOptions can be used to adjust various COSI access provisioning behaviors.
3446
// +optional
35-
Foo *string `json:"foo,omitempty"`
47+
FeatureOptions BucketAccessFeatureOptions `json:"featureOptions,omitempty"`
3648
}
3749

38-
// BucketAccessClassStatus defines the observed state of BucketAccessClass.
39-
type BucketAccessClassStatus 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 BucketAccessClass 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+
// BucketAccessFeatureOptions defines various COSI access provisioning behaviors.
51+
type BucketAccessFeatureOptions struct {
52+
// disallowedBucketAccessModes is a list of disallowed Read/Write access modes. A BucketAccess
53+
// using this class will not be allowed to request access to a BucketClaim with any access mode
54+
// listed here.
5755
// +optional
58-
Conditions []metav1.Condition `json:"conditions,omitempty"`
56+
// +listType=set
57+
DisallowedBucketAccessModes []BucketAccessMode `json:"disallowedBucketAccessModes,omitempty"`
58+
59+
// disallowMultiBucketAccess disables the ability for a BucketAccess to reference multiple
60+
// BucketClaims when set.
61+
// +optional
62+
DisallowMultiBucketAccess bool `json:"disallowMultiBucketAccess,omitempty"`
5963
}
6064

6165
// +kubebuilder:object:root=true
@@ -73,11 +77,8 @@ type BucketAccessClass struct {
7377

7478
// spec defines the desired state of BucketAccessClass
7579
// +required
80+
// +kubebuilder:validation:XValidation:message="BucketAccessClass spec is immutable",rule="self == oldSelf"
7681
Spec BucketAccessClassSpec `json:"spec"`
77-
78-
// status defines the observed state of BucketAccessClass
79-
// +optional
80-
Status BucketAccessClassStatus `json:"status,omitempty,omitzero"`
8182
}
8283

8384
// +kubebuilder:object:root=true

client/apis/objectstorage/v1alpha2/bucketclaim_types.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@ import (
2222

2323
// BucketClaimSpec defines the desired state of BucketClaim
2424
// +kubebuilder:validation:ExactlyOneOf=bucketClassName;existingBucketName
25+
// +kubebuilder:validation:XValidation:message="bucketClassName is immutable",rule="has(oldSelf.bucketClassName) == has(self.bucketClassName)"
26+
// +kubebuilder:validation:XValidation:message="existingBucketName is immutable",rule="has(oldSelf.existingBucketName) == has(self.existingBucketName)"
27+
// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="has(oldSelf.protocols) == has(self.protocols)"
2528
type BucketClaimSpec struct {
2629
// bucketClassName selects the BucketClass for provisioning the BucketClaim.
2730
// This field is used only for BucketClaim dynamic provisioning.
2831
// If unspecified, existingBucketName must be specified for binding to an existing Bucket.
2932
// +optional
33+
// +kubebuilder:validation:MaxLength=253
3034
// +kubebuilder:validation:XValidation:message="bucketClassName is immutable",rule="self == oldSelf"
3135
BucketClassName string `json:"bucketClassName,omitempty"`
3236

@@ -41,15 +45,19 @@ type BucketClaimSpec struct {
4145
// This field is used only for BucketClaim static provisioning.
4246
// If unspecified, bucketClassName must be specified for dynamically provisioning a new bucket.
4347
// +optional
48+
// +kubebuilder:validation:MaxLength=253
4449
// +kubebuilder:validation:XValidation:message="existingBucketName is immutable",rule="self == oldSelf"
4550
ExistingBucketName string `json:"existingBucketName,omitempty"`
4651
}
4752

4853
// BucketClaimStatus defines the observed state of BucketClaim.
54+
// +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="!has(oldSelf.boundBucketName) || has(self.boundBucketName)"
55+
// +kubebuilder:validation:XValidation:message="protocols is immutable once set",rule="!has(oldSelf.protocols) || has(self.protocols)"
4956
type BucketClaimStatus struct {
5057
// 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"
58+
// +optional
59+
// +kubebuilder:validation:MaxLength=253
60+
// +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="oldSelf == '' || self == oldSelf"
5361
BoundBucketName string `json:"boundBucketName"`
5462

5563
// readyToUse indicates that the bucket is ready for consumption by workloads.

client/apis/objectstorage/v1alpha2/protocols.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ This file describes the end-user representation of the various object store prot
2323
// TODO: can we write doc generation and linting for the definitions in this file?
2424

2525
// ObjectProtocol represents an object protocol type.
26+
// +kubebuilder:validation:Enum:=S3;Azure;GCS
2627
type ObjectProtocol string
2728

2829
const (

0 commit comments

Comments
 (0)