From 914c1d47d4c651532054dc199185028505afb5e4 Mon Sep 17 00:00:00 2001 From: Blaine Gardner Date: Fri, 5 Dec 2025 10:54:25 -0700 Subject: [PATCH] placeholder commit for purposes of reviewing API in PR --- .../objectstorage/v1alpha2/bucket_types.go | 175 +++++ .../v1alpha2/bucketaccess_types.go | 217 +++++++ .../v1alpha2/bucketaccessclass_types.go | 95 +++ .../v1alpha2/bucketclaim_types.go | 110 ++++ .../v1alpha2/bucketclass_types.go | 76 +++ .../objectstorage/v1alpha2/definitions.go | 56 ++ .../v1alpha2/groupversion_info.go | 36 ++ .../apis/objectstorage/v1alpha2/protocols.go | 146 +++++ .../objectstorage/v1alpha2/shared_types.go | 57 ++ .../v1alpha2/zz_generated.deepcopy.go | 609 ++++++++++++++++++ 10 files changed, 1577 insertions(+) create mode 100644 client2/apis/objectstorage/v1alpha2/bucket_types.go create mode 100644 client2/apis/objectstorage/v1alpha2/bucketaccess_types.go create mode 100644 client2/apis/objectstorage/v1alpha2/bucketaccessclass_types.go create mode 100644 client2/apis/objectstorage/v1alpha2/bucketclaim_types.go create mode 100644 client2/apis/objectstorage/v1alpha2/bucketclass_types.go create mode 100644 client2/apis/objectstorage/v1alpha2/definitions.go create mode 100644 client2/apis/objectstorage/v1alpha2/groupversion_info.go create mode 100644 client2/apis/objectstorage/v1alpha2/protocols.go create mode 100644 client2/apis/objectstorage/v1alpha2/shared_types.go create mode 100644 client2/apis/objectstorage/v1alpha2/zz_generated.deepcopy.go diff --git a/client2/apis/objectstorage/v1alpha2/bucket_types.go b/client2/apis/objectstorage/v1alpha2/bucket_types.go new file mode 100644 index 00000000..2817ab8f --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/bucket_types.go @@ -0,0 +1,175 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +// BucketDeletionPolicy configures COSI's behavior when a Bucket resource is deleted. +// +enum +// +kubebuilder:validation:Enum:=Retain;Delete +type BucketDeletionPolicy string + +const ( + // BucketDeletionPolicyRetain configures COSI to keep the Bucket object as well as the backend + // bucket when a Bucket resource is deleted. + BucketDeletionPolicyRetain BucketDeletionPolicy = "Retain" + + // BucketDeletionPolicyDelete configures COSI to delete the Bucket object as well as the backend + // bucket when a Bucket resource is deleted. + BucketDeletionPolicyDelete BucketDeletionPolicy = "Delete" +) + +// BucketSpec defines the desired state of Bucket +// +kubebuilder:validation:XValidation:message="parameters map is immutable",rule="has(oldSelf.parameters) == has(self.parameters)" +// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="has(oldSelf.protocols) == has(self.protocols)" +// +kubebuilder:validation:XValidation:message="existingBucketID is immutable",rule="has(oldSelf.existingBucketID) == has(self.existingBucketID)" +type BucketSpec struct { + // driverName is the name of the driver that fulfills requests for this Bucket. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:XValidation:message="driverName is immutable",rule="self == oldSelf" + DriverName string `json:"driverName"` + + // deletionPolicy determines whether a Bucket should be deleted when its bound BucketClaim is + // deleted. This is mutable to allow Admins to change the policy after creation. + // Possible values: + // - Retain: keep both the Bucket object and the backend bucket + // - Delete: delete both the Bucket object and the backend bucket + // +required + DeletionPolicy BucketDeletionPolicy `json:"deletionPolicy"` + + // parameters is an opaque map of driver-specific configuration items passed to the driver that + // fulfills requests for this Bucket. + // +optional + // +kubebuilder:validation:XValidation:message="parameters map is immutable",rule="self == oldSelf" + Parameters map[string]string `json:"parameters,omitempty"` + + // protocols lists object store protocols that the provisioned Bucket must support. + // If specified, COSI will verify that each item is advertised as supported by the driver. + // +optional + // +listType=set + // +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="self == oldSelf" + Protocols []ObjectProtocol `json:"protocols,omitempty"` + + // bucketClaim references the BucketClaim that resulted in the creation of this Bucket. + // For statically-provisioned buckets, set the namespace and name of the BucketClaim that is + // allowed to bind to this Bucket. + // +required + BucketClaimRef BucketClaimReference `json:"bucketClaim"` + + // existingBucketID is the unique identifier for an existing backend bucket known to the driver. + // Use driver documentation to determine how to set this value. + // This field is used only for Bucket static provisioning. + // This field will be empty when the Bucket is dynamically provisioned from a BucketClaim. + // +optional + // +kubebuilder:validation:XValidation:message="existingBucketID is immutable",rule="self == oldSelf" + ExistingBucketID string `json:"existingBucketID,omitempty"` +} + +// BucketClaimReference is a reference to a BucketClaim object. +// +kubebuilder:validation:XValidation:message="namespace is immutable once set",rule="!has(oldSelf.namespace) || has(self.namespace)" +// +kubebuilder:validation:XValidation:message="uid is immutable once set",rule="!has(oldSelf.uid) || has(self.uid)" +type BucketClaimReference struct { + // name is the name of the BucketClaim being referenced. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="name is immutable",rule="self == oldSelf" + Name string `json:"name"` + + // namespace is the namespace of the BucketClaim being referenced. + // If empty, the Kubernetes 'default' namespace is assumed. + // namespace is immutable except to update '' to 'default'. + // +optional + // +kubebuilder:validation:MinLength=0 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="namespace is immutable",rule="(oldSelf == '' && self == 'default') || self == oldSelf" + Namespace string `json:"namespace"` + + // uid is the UID of the BucketClaim being referenced. + // +optional + // +kubebuilder:validation:XValidation:message="uid is immutable once set",rule="oldSelf == '' || self == oldSelf" + UID types.UID `json:"uid"` +} + +// BucketStatus defines the observed state of Bucket. +// +kubebuilder:validation:XValidation:message="bucketID is immutable once set",rule="!has(oldSelf.bucketID) || has(self.bucketID)" +// +kubebuilder:validation:XValidation:message="protocols is immutable once set",rule="!has(oldSelf.protocols) || has(self.protocols)" +type BucketStatus struct { + // readyToUse indicates that the bucket is ready for consumption by workloads. + ReadyToUse bool `json:"readyToUse"` + + // bucketID is the unique identifier for the backend bucket known to the driver. + // +optional + // +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="oldSelf == '' || self == oldSelf" + BucketID string `json:"bucketID"` + + // protocols is the set of protocols the Bucket reports to support. BucketAccesses can request + // access to this BucketClaim using any of the protocols reported here. + // +optional + // +listType=set + Protocols []ObjectProtocol `json:"protocols"` + + // BucketInfo reported by the driver, rendered in the COSI__ format used for the + // BucketAccess Secret. e.g., COSI_S3_ENDPOINT, COSI_AZURE_STORAGE_ACCOUNT. + // This should not contain any sensitive information. + // +optional + BucketInfo map[string]string `json:"bucketInfo,omitempty"` + + // Error holds the most recent error message, with a timestamp. + // This is cleared when provisioning is successful. + // +optional + Error *TimestampedError `json:"error,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes" + +// Bucket is the Schema for the buckets API +type Bucket struct { + metav1.TypeMeta `json:",inline"` + + // metadata is a standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty,omitzero"` + + // spec defines the desired state of Bucket + // +required + Spec BucketSpec `json:"spec"` + + // status defines the observed state of Bucket + // +optional + Status BucketStatus `json:"status,omitempty,omitzero"` +} + +// +kubebuilder:object:root=true + +// BucketList contains a list of Bucket +type BucketList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Bucket `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Bucket{}, &BucketList{}) +} diff --git a/client2/apis/objectstorage/v1alpha2/bucketaccess_types.go b/client2/apis/objectstorage/v1alpha2/bucketaccess_types.go new file mode 100644 index 00000000..9a38c277 --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/bucketaccess_types.go @@ -0,0 +1,217 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BucketAccessAuthenticationType specifies what authentication mechanism is used for provisioning +// bucket access. +// +enum +// +kubebuilder:validation:Enum:="";Key;ServiceAccount +type BucketAccessAuthenticationType string + +const ( + // The driver should generate a protocol-appropriate access key that clients can use to + // authenticate to the backend object store. + BucketAccessAuthenticationTypeKey = "Key" + + // The driver should configure the system such that Pods using the given ServiceAccount + // authenticate to the backend object store automatically. + BucketAccessAuthenticationTypeServiceAccount = "ServiceAccount" +) + +// BucketAccessMode describes the Read/Write mode an access should have for a bucket. +// +enum +// +kubebuilder:validation:Enum:=ReadWrite;ReadOnly;WriteOnly +type BucketAccessMode string + +const ( + // BucketAccessModeReadWrite represents read-write access mode. + BucketAccessModeReadWrite BucketAccessMode = "ReadWrite" + + // BucketAccessModeReadOnly represents read-only access mode. + BucketAccessModeReadOnly BucketAccessMode = "ReadOnly" + + // BucketAccessModeWriteOnly represents write-only access mode. + BucketAccessModeWriteOnly BucketAccessMode = "WriteOnly" +) + +// BucketAccessSpec defines the desired state of BucketAccess +// +kubebuilder:validation:XValidation:message="serviceAccountName is immutable",rule="has(oldSelf.serviceAccountName) == has(self.serviceAccountName)" +type BucketAccessSpec struct { + // bucketClaims is a list of BucketClaims the provisioned access must have permissions for, + // along with per-BucketClaim access parameters and system output definitions. + // At least one BucketClaim must be referenced. + // Multiple references to the same BucketClaim are not permitted. + // +required + // +listType=map + // +listMapKey=bucketClaimName + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:XValidation:message="bucketClaims list is immutable",rule="self == oldSelf" + BucketClaims []BucketClaimAccess `json:"bucketClaims"` + + // bucketAccessClassName selects the BucketAccessClass for provisioning the access. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="bucketAccessClassName is immutable",rule="self == oldSelf" + BucketAccessClassName string `json:"bucketAccessClassName"` + + // protocol is the object storage protocol that the provisioned access must use. + // +required + // +kubebuilder:validation:XValidation:message="protocol is immutable",rule="self == oldSelf" + Protocol ObjectProtocol `json:"protocol"` + + // serviceAccountName is the name of the Kubernetes ServiceAccount that user application Pods + // intend to use for access to referenced BucketClaims. + // This has different behavior based on the BucketAccessClass's defined AuthenticationType: + // - Key: This field is ignored. + // - ServiceAccount: This field is required. The driver should configure the system so that Pods + // using the ServiceAccount authenticate to the object storage backend automatically. + // +optional + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="serviceAccountName is immutable",rule="self == oldSelf" + ServiceAccountName string `json:"serviceAccountName,omitempty"` +} + +// BucketAccessStatus defines the observed state of BucketAccess. +// +kubebuilder:validation:XValidation:message="accountID is immutable once set",rule="!has(oldSelf.accountID) || has(self.accountID)" +// +kubebuilder:validation:XValidation:message="accessedBuckets is immutable once set",rule="!has(oldSelf.accessedBuckets) || has(self.accessedBuckets)" +// +kubebuilder:validation:XValidation:message="driverName is immutable once set",rule="!has(oldSelf.driverName) || has(self.driverName)" +// +kubebuilder:validation:XValidation:message="authenticationType is immutable once set",rule="!has(oldSelf.authenticationType) || has(self.authenticationType)" +// +kubebuilder:validation:XValidation:message="parameters is immutable once set",rule="!has(oldSelf.parameters) || has(self.parameters)" +type BucketAccessStatus struct { + // readyToUse indicates that the BucketAccess is ready for consumption by workloads. + ReadyToUse bool `json:"readyToUse"` + + // accountID is the unique identifier for the backend access known to the driver. + // This field is populated by the COSI Sidecar once access has been successfully granted. + // +optional + // +kubebuilder:validation:XValidation:message="accountId is immutable once set",rule="oldSelf == '' || self == oldSelf" + AccountID string `json:"accountID"` + + // accessedBuckets is a list of Buckets the provisioned access must have permissions for, along + // with per-Bucket access options. This field is populated by the COSI Controller based on the + // referenced BucketClaims in the spec. + // +optional + // +listType=map + // +listMapKey=bucketName + // +kubebuilder:validation:XValidation:message="accessedBuckets is immutable once set",rule="oldSelf.size() == 0 || self == oldSelf" + AccessedBuckets []AccessedBucket `json:"accessedBuckets"` + + // driverName holds a copy of the BucketAccessClass driver name from the time of BucketAccess + // provisioning. This field is populated by the COSI Controller. + // +optional + // +kubebuilder:validation:XValidation:message="driverName is immutable once set",rule="oldSelf == '' || self == oldSelf" + DriverName string `json:"driverName"` + + // authenticationType holds a copy of the BucketAccessClass authentication type from the time of + // BucketAccess provisioning. This field is populated by the COSI Controller. + // +optional + // +kubebuilder:validation:XValidation:message="authenticationType is immutable once set",rule="oldSelf == '' || self == oldSelf" + AuthenticationType BucketAccessAuthenticationType `json:"authenticationType"` + + // parameters holds a copy of the BucketAccessClass parameters from the time of BucketAccess + // provisioning. This field is populated by the COSI Controller. + // +optional + // +kubebuilder:validation:XValidation:message="accessedBuckets is immutable once set",rule="oldSelf.size() == 0 || self == oldSelf" + Parameters map[string]string `json:"parameters,omitempty"` + + // error holds the most recent error message, with a timestamp. + // This is cleared when provisioning is successful. + // +optional + Error *TimestampedError `json:"error,omitempty"` +} + +// BucketClaimAccess selects a BucketClaim for access, defines access parameters for the +// corresponding bucket, and specifies where user-consumable bucket information and access +// credentials for the accessed bucket will be stored. +type BucketClaimAccess struct { + // bucketClaimName is the name of a BucketClaim the access should have permissions for. + // The BucketClaim must be in the same Namespace as the BucketAccess. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + BucketClaimName string `json:"bucketClaimName"` + + // accessMode is the Read/Write access mode that the access should have for the bucket. + // Possible values: ReadWrite, ReadOnly, WriteOnly. + // +required + AccessMode BucketAccessMode `json:"accessMode"` + + // accessSecretName is the name of a Kubernetes Secret that COSI should create and populate with + // bucket info and access credentials for the bucket. + // The Secret is created in the same Namespace as the BucketAccess and is deleted when the + // BucketAccess is deleted and deprovisioned. + // The Secret name must be unique across all bucketClaimRefs for all BucketAccesses in the same + // Namespace. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + AccessSecretName string `json:"accessSecretName"` +} + +// AccessedBucket identifies a Bucket and correlates it to a BucketClaimAccess from the spec. +type AccessedBucket struct { + // bucketName is the name of a Bucket the access should have permissions for. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + BucketName string `json:"bucketName"` + + // bucketClaimName must match a BucketClaimAccess's BucketClaimName from the spec. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=253 + BucketClaimName string `json:"bucketClaimName"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes" + +// BucketAccess is the Schema for the bucketaccesses API +type BucketAccess struct { + metav1.TypeMeta `json:",inline"` + + // metadata is a standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty,omitzero"` + + // spec defines the desired state of BucketAccess + // +required + Spec BucketAccessSpec `json:"spec"` + + // status defines the observed state of BucketAccess + // +optional + Status BucketAccessStatus `json:"status,omitempty,omitzero"` +} + +// +kubebuilder:object:root=true + +// BucketAccessList contains a list of BucketAccess +type BucketAccessList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BucketAccess `json:"items"` +} + +func init() { + SchemeBuilder.Register(&BucketAccess{}, &BucketAccessList{}) +} diff --git a/client2/apis/objectstorage/v1alpha2/bucketaccessclass_types.go b/client2/apis/objectstorage/v1alpha2/bucketaccessclass_types.go new file mode 100644 index 00000000..97b7ae38 --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/bucketaccessclass_types.go @@ -0,0 +1,95 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BucketAccessClassSpec defines the desired state of BucketAccessClass +type BucketAccessClassSpec struct { + // driverName is the name of the driver that fulfills requests for this BucketAccessClass. + // +required + // +kubebuilder:validation:MinLength=1 + DriverName string `json:"driverName"` + + // authenticationType specifies which authentication mechanism is used bucket access. + // Possible values: + // - Key: The driver should generate a protocol-appropriate access key that clients can use to + // authenticate to the backend object store. + // - ServiceAccount: The driver should configure the system such that Pods using the given + // ServiceAccount authenticate to the backend object store automatically. + // +required + // +kubebuilder:validation:Enum:=Key;ServiceAccount + AuthenticationType BucketAccessAuthenticationType `json:"authenticationType"` + + // parameters is an opaque map of driver-specific configuration items passed to the driver that + // fulfills requests for this BucketAccessClass. + // +optional + Parameters map[string]string `json:"parameters,omitempty"` + + // featureOptions can be used to adjust various COSI access provisioning behaviors. + // +optional + FeatureOptions BucketAccessFeatureOptions `json:"featureOptions,omitempty"` +} + +// BucketAccessFeatureOptions defines various COSI access provisioning behaviors. +type BucketAccessFeatureOptions struct { + // disallowedBucketAccessModes is a list of disallowed Read/Write access modes. A BucketAccess + // using this class will not be allowed to request access to a BucketClaim with any access mode + // listed here. + // +optional + // +listType=set + DisallowedBucketAccessModes []BucketAccessMode `json:"disallowedBucketAccessModes,omitempty"` + + // disallowMultiBucketAccess disables the ability for a BucketAccess to reference multiple + // BucketClaims when set. + // +optional + DisallowMultiBucketAccess bool `json:"disallowMultiBucketAccess,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes" + +// BucketAccessClass is the Schema for the bucketaccessclasses API +type BucketAccessClass struct { + metav1.TypeMeta `json:",inline"` + + // metadata is a standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty,omitzero"` + + // spec defines the desired state of BucketAccessClass + // +required + // +kubebuilder:validation:XValidation:message="BucketAccessClass spec is immutable",rule="self == oldSelf" + Spec BucketAccessClassSpec `json:"spec"` +} + +// +kubebuilder:object:root=true + +// BucketAccessClassList contains a list of BucketAccessClass +type BucketAccessClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BucketAccessClass `json:"items"` +} + +func init() { + SchemeBuilder.Register(&BucketAccessClass{}, &BucketAccessClassList{}) +} diff --git a/client2/apis/objectstorage/v1alpha2/bucketclaim_types.go b/client2/apis/objectstorage/v1alpha2/bucketclaim_types.go new file mode 100644 index 00000000..5410a4ed --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/bucketclaim_types.go @@ -0,0 +1,110 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BucketClaimSpec defines the desired state of BucketClaim +// +kubebuilder:validation:ExactlyOneOf=bucketClassName;existingBucketName +// +kubebuilder:validation:XValidation:message="bucketClassName is immutable",rule="has(oldSelf.bucketClassName) == has(self.bucketClassName)" +// +kubebuilder:validation:XValidation:message="existingBucketName is immutable",rule="has(oldSelf.existingBucketName) == has(self.existingBucketName)" +// +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="has(oldSelf.protocols) == has(self.protocols)" +type BucketClaimSpec struct { + // bucketClassName selects the BucketClass for provisioning the BucketClaim. + // This field is used only for BucketClaim dynamic provisioning. + // If unspecified, existingBucketName must be specified for binding to an existing Bucket. + // +optional + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="bucketClassName is immutable",rule="self == oldSelf" + BucketClassName string `json:"bucketClassName,omitempty"` + + // protocols lists object storage protocols that the provisioned Bucket must support. + // If specified, COSI will verify that each item is advertised as supported by the driver. + // +optional + // +kubebuilder:validation:XValidation:message="protocols list is immutable",rule="self == oldSelf" + Protocols []ObjectProtocol `json:"protocols,omitempty"` + + // existingBucketName selects the name of an existing Bucket resource that this BucketClaim + // should bind to. + // This field is used only for BucketClaim static provisioning. + // If unspecified, bucketClassName must be specified for dynamically provisioning a new bucket. + // +optional + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="existingBucketName is immutable",rule="self == oldSelf" + ExistingBucketName string `json:"existingBucketName,omitempty"` +} + +// BucketClaimStatus defines the observed state of BucketClaim. +// +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="!has(oldSelf.boundBucketName) || has(self.boundBucketName)" +// +kubebuilder:validation:XValidation:message="protocols is immutable once set",rule="!has(oldSelf.protocols) || has(self.protocols)" +type BucketClaimStatus struct { + // boundBucketName is the name of the Bucket this BucketClaim is bound to. + // +optional + // +kubebuilder:validation:MaxLength=253 + // +kubebuilder:validation:XValidation:message="boundBucketName is immutable once set",rule="oldSelf == '' || self == oldSelf" + BoundBucketName string `json:"boundBucketName"` + + // readyToUse indicates that the bucket is ready for consumption by workloads. + ReadyToUse bool `json:"readyToUse"` + + // protocols is the set of protocols the bound Bucket reports to support. BucketAccesses can + // request access to this BucketClaim using any of the protocols reported here. + // +optional + // +listType=set + Protocols []ObjectProtocol `json:"protocols"` + + // error holds the most recent error message, with a timestamp. + // This is cleared when provisioning is successful. + // +optional + Error *TimestampedError `json:"error,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes" + +// BucketClaim is the Schema for the bucketclaims API +type BucketClaim struct { + metav1.TypeMeta `json:",inline"` + + // metadata is a standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty,omitzero"` + + // spec defines the desired state of BucketClaim + // +required + Spec BucketClaimSpec `json:"spec"` + + // status defines the observed state of BucketClaim + // +optional + Status BucketClaimStatus `json:"status,omitempty,omitzero"` +} + +// +kubebuilder:object:root=true + +// BucketClaimList contains a list of BucketClaim +type BucketClaimList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BucketClaim `json:"items"` +} + +func init() { + SchemeBuilder.Register(&BucketClaim{}, &BucketClaimList{}) +} diff --git a/client2/apis/objectstorage/v1alpha2/bucketclass_types.go b/client2/apis/objectstorage/v1alpha2/bucketclass_types.go new file mode 100644 index 00000000..6b1b376c --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/bucketclass_types.go @@ -0,0 +1,76 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BucketClassSpec defines the BucketClass. +type BucketClassSpec struct { + // driverName is the name of the driver that fulfills requests for this BucketClass. + // +required + // +kubebuilder:validation:MinLength=1 + DriverName string `json:"driverName"` + + // deletionPolicy determines whether a Bucket created through the BucketClass should be deleted + // when its bound BucketClaim is deleted. + // Possible values: + // - Retain: keep both the Bucket object and the backend bucket + // - Delete: delete both the Bucket object and the backend bucket + // +required + DeletionPolicy BucketDeletionPolicy `json:"deletionPolicy"` + + // parameters is an opaque map of driver-specific configuration items passed to the driver that + // fulfills requests for this BucketClass. + // +optional + Parameters map[string]string `json:"parameters,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Cluster +// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=unapproved, experimental v1alpha2 changes" + +// BucketClass defines a named "class" of object storage buckets. +// Different classes might map to different object storage protocols, quality-of-service levels, +// backup policies, or any other arbitrary configuration determined by storage administrators. +// The name of a BucketClass object is significant, and is how users can request a particular class. +type BucketClass struct { + metav1.TypeMeta `json:",inline"` + + // metadata is a standard object metadata + // +optional + metav1.ObjectMeta `json:"metadata,omitempty,omitzero"` + + // spec defines the BucketClass. spec is entirely immutable. + // +required + // +kubebuilder:validation:XValidation:message="BucketClass spec is immutable",rule="self == oldSelf" + Spec BucketClassSpec `json:"spec"` +} + +// +kubebuilder:object:root=true + +// BucketClassList contains a list of BucketClass +type BucketClassList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []BucketClass `json:"items"` +} + +func init() { + SchemeBuilder.Register(&BucketClass{}, &BucketClassList{}) +} diff --git a/client2/apis/objectstorage/v1alpha2/definitions.go b/client2/apis/objectstorage/v1alpha2/definitions.go new file mode 100644 index 00000000..162b76fc --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/definitions.go @@ -0,0 +1,56 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +// Finalizers +const ( + // ProtectionFinalizer is applied to a COSI resource object to protect it from deletion while + // COSI processes deletion of the object's intermediate and backend resources. + ProtectionFinalizer = `objectstorage.k8s.io/protection` +) + +// Annotations +const ( + // HasBucketAccessReferencesAnnotation : This annotation is applied by the COSI Controller to a + // BucketClaim when a BucketAccess that references the BucketClaim is created. The annotation + // remains for as long as any BucketAccess references the BucketClaim. Once all BucketAccesses + // that reference the BucketClaim are deleted, the annotation is removed. + HasBucketAccessReferencesAnnotation = `objectstorage.k8s.io/has-bucketaccess-references` + + // SidecarCleanupFinishedAnnotation : This annotation is applied by a COSI Sidecar to a managed + // BucketAccess when the resources is being deleted. The Sidecar calls the Driver to perform + // backend deletion actions and then hands off final deletion cleanup to the COSI Controller + // by setting this annotation on the resource. + SidecarCleanupFinishedAnnotation = `objectstorage.k8s.io/sidecar-cleanup-finished` + + // ControllerManagementOverrideAnnotation : This annotation can be applied to a resource by the + // COSI Controller in order to reclaim management of the resource temporarily when it would + // otherwise be managed by a COSI Sidecar. This is intended for scenarios where a bug in + // provisioning needs to be rectified by a newer version of the COSI Controller. Once the bug is + // resolved, the annotation should be removed to allow normal Sidecar handoff to occur. + ControllerManagementOverrideAnnotation = `objectstorage.k8s.io/controller-management-override` +) + +// Sidecar RPC definitions +const ( + // RpcEndpointDefault is the default RPC endpoint unix socket location. + RpcEndpointDefault = "unix:///var/lib/cosi/cosi.sock" + + // RpcEndpointEnvVarName is the name of the environment variable that is expected to hold the + // RPC endpoint unix socket location. If unspecified, RpcEndpointDefault should be used. + RpcEndpointEnvVarName = "COSI_ENDPOINT" +) diff --git a/client2/apis/objectstorage/v1alpha2/groupversion_info.go b/client2/apis/objectstorage/v1alpha2/groupversion_info.go new file mode 100644 index 00000000..3c534ba4 --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1alpha2 contains API Schema definitions for the objectstorage v1alpha2 API group. +// +kubebuilder:object:generate=true +// +groupName=objectstorage.k8s.io +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "objectstorage.k8s.io", Version: "v1alpha2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/client2/apis/objectstorage/v1alpha2/protocols.go b/client2/apis/objectstorage/v1alpha2/protocols.go new file mode 100644 index 00000000..737e01f4 --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/protocols.go @@ -0,0 +1,146 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +/* +This file describes the end-user representation of the various object store protocols. +*/ + +// TODO: can we write doc generation and linting for the definitions in this file? + +// ObjectProtocol represents an object protocol type. +// +kubebuilder:validation:Enum:=S3;Azure;GCS +type ObjectProtocol string + +const ( + // ObjectProtocolS3 represents the S3 object protocol type. + ObjectProtocolS3 ObjectProtocol = "S3" + + // ObjectProtocolS3 represents the Azure Blob object protocol type. + ObjectProtocolAzure ObjectProtocol = "Azure" + + // ObjectProtocolS3 represents the Google Cloud Storage object protocol type. + ObjectProtocolGcs ObjectProtocol = "GCS" +) + +// A CosiEnvVar defines a COSI environment variable that contains backend bucket or access info. +// Vars marked "Required" will be present with non-empty values in BucketAccess Secrets. +// Some required vars may only be required in certain contexts, like when a specific +// AuthenticationType is used. +// Some vars are only relevant for specific protocols. +// Non-relevant vars will not be present, even when marked "Required". +// Vars are used as data keys in BucketAccess Secrets. +// Vars must be all-caps and must begin with `COSI_`. +type CosiEnvVar string + +// A BucketInfoVar defines a protocol-specific COSI environment variable that contains backend +// bucket info. +// All protocol-specific vars include the all-caps protocol name after `COSI_`. E.g., `COSI_AZURE_`. +type BucketInfoVar CosiEnvVar + +// A CredentialVar defines a protocol-specific COSI environment variable that contains backend +// bucket access credential info. +// All protocol-specific vars include the all-caps protocol name after `COSI_`. E.g., `COSI_AZURE_`. +type CredentialVar CosiEnvVar + +const ( + // Required. The protocol associated with a BucketAccess. + // Will be a string representing an ObjectProtocol type. + BucketInfoVar_Protocol BucketInfoVar = "COSI_PROTOCOL" + + // Optional. The certificate authority that clients can use to authenticate a BucketAccess. + CredentialVar_CertificateAuthority CredentialVar = "COSI_CERTIFICATE_AUTHORITY" +) + +/* + * S3 protocol variables + */ + +// bucket info vars +const ( + // Required. The S3 bucket ID as used by clients. + BucketInfoVar_S3_BucketId BucketInfoVar = "COSI_S3_BUCKET_ID" + + // Required. The S3 endpoint for the bucket. + BucketInfoVar_S3_Endpoint BucketInfoVar = "COSI_S3_ENDPOINT" + + // Required. The S3 region for the bucket. + BucketInfoVar_S3_Region BucketInfoVar = "COSI_S3_REGION" + + // Required. The S3 addressing style. One of `path` or `virtual`. + // See: https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html. + BucketInfoVar_S3_AddressingStyle BucketInfoVar = "COSI_S3_ADDRESSING_STYLE" +) + +// nolint:gosec // credential vars, not hardcoded credentials +const ( + // Required for `AuthenticationType=Key`. The S3 access key ID. + CredentialVar_S3_AccessKeyId CredentialVar = "COSI_S3_ACCESS_KEY_ID" // nolint:gosec // no a cred + + // Required for `AuthenticationType=Key`. The S3 access secret key. + CredentialVar_S3_AccessSecretKey CredentialVar = "COSI_S3_ACCESS_SECRET_KEY" // nolint:gosec // no a cred +) + +/* + * Azure protocol variables + */ + +// bucket info vars +const ( + // Required. The ID of the Azure storage account. + BucketInfoVar_Azure_StorageAccount BucketInfoVar = "COSI_AZURE_STORAGE_ACCOUNT" +) + +// nolint:gosec // credential vars, not hardcoded credentials +const ( + // Required for `AuthenticationType=Key`. Azure SAS access token. + // Note that this includes the resource URI as well as token in its definition. + // See: https://learn.microsoft.com/en-us/azure/storage/common/media/storage-sas-overview/sas-storage-uri.svg + CredentialVar_Azure_AccessToken CredentialVar = "COSI_AZURE_ACCESS_TOKEN" + + // Optional. The timestamp when access will expire. + // Empty if unset. Otherwise, date+time in ISO 8601 format. + CredentialVar_Azure_ExpiryTimestamp CredentialVar = "COSI_AZURE_EXPIRY_TIMESTAMP" +) + +/* + * Google Cloud Storage (GCS) protocol variables + */ + +// bucket info vars +const ( + // Required. The GCS project ID. + BucketInfoVar_GCS_ProjectId BucketInfoVar = "COSI_GCS_PROJECT_ID" + + // Required. GCS bucket name as used by clients. + BucketInfoVar_GCS_BucketName BucketInfoVar = "COSI_GCS_BUCKET_NAME" +) + +// nolint:gosec // credential vars, not hardcoded credentials +const ( + // Required for `AuthenticationType=Key`. HMAC access ID. + CredentialVar_GCS_AccessId CredentialVar = "COSI_GCS_ACCESS_ID" + + // Required for `AuthenticationType=Key`. HMAC secret. + CredentialVar_GCS_AccessSecret CredentialVar = "COSI_GCS_ACCESS_SECRET" + + // GCS private key name. + CredentialVar_GCS_PrivateKeyName CredentialVar = "COSI_GCS_PRIVATE_KEY_NAME" + + // GCS service account name. + CredentialVar_GCS_ServiceAccount CredentialVar = "COSI_GCS_SERVICE_ACCOUNT" +) diff --git a/client2/apis/objectstorage/v1alpha2/shared_types.go b/client2/apis/objectstorage/v1alpha2/shared_types.go new file mode 100644 index 00000000..c27ee6b8 --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/shared_types.go @@ -0,0 +1,57 @@ +/* +Copyright 2025 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha2 + +/* +This file for types that don't belong to any COSI resource specifically. +Use `_types.go` files for resource-specific types. +*/ + +import ( + "time" + + meta "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TimestampedError contains an error message with timestamp. +type TimestampedError struct { + // time is the timestamp when the error was encountered. + // +optional + Time *meta.Time `json:"time,omitempty" protobuf:"bytes,1,opt,name=time"` + + // message is a string detailing the encountered error. + // NOTE: message will be logged, and it should not contain sensitive information. + // +optional + Message *string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"` +} + +// NewTimestampedError creates a TimestampedError with the given info. +// Result fields will be nil for zero-value inputs. +func NewTimestampedError(t time.Time, message string) *TimestampedError { + tp := &meta.Time{Time: t} + if tp.IsZero() { + tp = nil + } + mp := &message + if *mp == "" { + mp = nil + } + return &TimestampedError{ + Time: tp, + Message: mp, + } +} diff --git a/client2/apis/objectstorage/v1alpha2/zz_generated.deepcopy.go b/client2/apis/objectstorage/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 00000000..e4d63e2e --- /dev/null +++ b/client2/apis/objectstorage/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,609 @@ +//go:build !ignore_autogenerated + +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AccessedBucket) DeepCopyInto(out *AccessedBucket) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AccessedBucket. +func (in *AccessedBucket) DeepCopy() *AccessedBucket { + if in == nil { + return nil + } + out := new(AccessedBucket) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Bucket) DeepCopyInto(out *Bucket) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Bucket. +func (in *Bucket) DeepCopy() *Bucket { + if in == nil { + return nil + } + out := new(Bucket) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Bucket) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccess) DeepCopyInto(out *BucketAccess) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccess. +func (in *BucketAccess) DeepCopy() *BucketAccess { + if in == nil { + return nil + } + out := new(BucketAccess) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketAccess) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessClass) DeepCopyInto(out *BucketAccessClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessClass. +func (in *BucketAccessClass) DeepCopy() *BucketAccessClass { + if in == nil { + return nil + } + out := new(BucketAccessClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketAccessClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessClassList) DeepCopyInto(out *BucketAccessClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BucketAccessClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessClassList. +func (in *BucketAccessClassList) DeepCopy() *BucketAccessClassList { + if in == nil { + return nil + } + out := new(BucketAccessClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketAccessClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessClassSpec) DeepCopyInto(out *BucketAccessClassSpec) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + in.FeatureOptions.DeepCopyInto(&out.FeatureOptions) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessClassSpec. +func (in *BucketAccessClassSpec) DeepCopy() *BucketAccessClassSpec { + if in == nil { + return nil + } + out := new(BucketAccessClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessFeatureOptions) DeepCopyInto(out *BucketAccessFeatureOptions) { + *out = *in + if in.DisallowedBucketAccessModes != nil { + in, out := &in.DisallowedBucketAccessModes, &out.DisallowedBucketAccessModes + *out = make([]BucketAccessMode, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessFeatureOptions. +func (in *BucketAccessFeatureOptions) DeepCopy() *BucketAccessFeatureOptions { + if in == nil { + return nil + } + out := new(BucketAccessFeatureOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessList) DeepCopyInto(out *BucketAccessList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BucketAccess, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessList. +func (in *BucketAccessList) DeepCopy() *BucketAccessList { + if in == nil { + return nil + } + out := new(BucketAccessList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketAccessList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessSpec) DeepCopyInto(out *BucketAccessSpec) { + *out = *in + if in.BucketClaims != nil { + in, out := &in.BucketClaims, &out.BucketClaims + *out = make([]BucketClaimAccess, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessSpec. +func (in *BucketAccessSpec) DeepCopy() *BucketAccessSpec { + if in == nil { + return nil + } + out := new(BucketAccessSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketAccessStatus) DeepCopyInto(out *BucketAccessStatus) { + *out = *in + if in.AccessedBuckets != nil { + in, out := &in.AccessedBuckets, &out.AccessedBuckets + *out = make([]AccessedBucket, len(*in)) + copy(*out, *in) + } + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Error != nil { + in, out := &in.Error, &out.Error + *out = new(TimestampedError) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketAccessStatus. +func (in *BucketAccessStatus) DeepCopy() *BucketAccessStatus { + if in == nil { + return nil + } + out := new(BucketAccessStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClaim) DeepCopyInto(out *BucketClaim) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClaim. +func (in *BucketClaim) DeepCopy() *BucketClaim { + if in == nil { + return nil + } + out := new(BucketClaim) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketClaim) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClaimAccess) DeepCopyInto(out *BucketClaimAccess) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClaimAccess. +func (in *BucketClaimAccess) DeepCopy() *BucketClaimAccess { + if in == nil { + return nil + } + out := new(BucketClaimAccess) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClaimList) DeepCopyInto(out *BucketClaimList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BucketClaim, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClaimList. +func (in *BucketClaimList) DeepCopy() *BucketClaimList { + if in == nil { + return nil + } + out := new(BucketClaimList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketClaimList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClaimReference) DeepCopyInto(out *BucketClaimReference) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClaimReference. +func (in *BucketClaimReference) DeepCopy() *BucketClaimReference { + if in == nil { + return nil + } + out := new(BucketClaimReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClaimSpec) DeepCopyInto(out *BucketClaimSpec) { + *out = *in + if in.Protocols != nil { + in, out := &in.Protocols, &out.Protocols + *out = make([]ObjectProtocol, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClaimSpec. +func (in *BucketClaimSpec) DeepCopy() *BucketClaimSpec { + if in == nil { + return nil + } + out := new(BucketClaimSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClaimStatus) DeepCopyInto(out *BucketClaimStatus) { + *out = *in + if in.Protocols != nil { + in, out := &in.Protocols, &out.Protocols + *out = make([]ObjectProtocol, len(*in)) + copy(*out, *in) + } + if in.Error != nil { + in, out := &in.Error, &out.Error + *out = new(TimestampedError) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClaimStatus. +func (in *BucketClaimStatus) DeepCopy() *BucketClaimStatus { + if in == nil { + return nil + } + out := new(BucketClaimStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClass) DeepCopyInto(out *BucketClass) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClass. +func (in *BucketClass) DeepCopy() *BucketClass { + if in == nil { + return nil + } + out := new(BucketClass) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketClass) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClassList) DeepCopyInto(out *BucketClassList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]BucketClass, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClassList. +func (in *BucketClassList) DeepCopy() *BucketClassList { + if in == nil { + return nil + } + out := new(BucketClassList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketClassList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketClassSpec) DeepCopyInto(out *BucketClassSpec) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketClassSpec. +func (in *BucketClassSpec) DeepCopy() *BucketClassSpec { + if in == nil { + return nil + } + out := new(BucketClassSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketList) DeepCopyInto(out *BucketList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Bucket, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketList. +func (in *BucketList) DeepCopy() *BucketList { + if in == nil { + return nil + } + out := new(BucketList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *BucketList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketSpec) DeepCopyInto(out *BucketSpec) { + *out = *in + if in.Parameters != nil { + in, out := &in.Parameters, &out.Parameters + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Protocols != nil { + in, out := &in.Protocols, &out.Protocols + *out = make([]ObjectProtocol, len(*in)) + copy(*out, *in) + } + out.BucketClaimRef = in.BucketClaimRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketSpec. +func (in *BucketSpec) DeepCopy() *BucketSpec { + if in == nil { + return nil + } + out := new(BucketSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BucketStatus) DeepCopyInto(out *BucketStatus) { + *out = *in + if in.Protocols != nil { + in, out := &in.Protocols, &out.Protocols + *out = make([]ObjectProtocol, len(*in)) + copy(*out, *in) + } + if in.BucketInfo != nil { + in, out := &in.BucketInfo, &out.BucketInfo + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Error != nil { + in, out := &in.Error, &out.Error + *out = new(TimestampedError) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BucketStatus. +func (in *BucketStatus) DeepCopy() *BucketStatus { + if in == nil { + return nil + } + out := new(BucketStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TimestampedError) DeepCopyInto(out *TimestampedError) { + *out = *in + if in.Time != nil { + in, out := &in.Time, &out.Time + *out = (*in).DeepCopy() + } + if in.Message != nil { + in, out := &in.Message, &out.Message + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TimestampedError. +func (in *TimestampedError) DeepCopy() *TimestampedError { + if in == nil { + return nil + } + out := new(TimestampedError) + in.DeepCopyInto(out) + return out +}