Initial cephrgw-operator: Ceph RGW buckets & keys via dashboard API

Adds a Kubernetes operator that provisions Ceph RGW (S3) buckets and
access keys declaratively through the Ceph manager dashboard REST API.

Three CRDs in group ceph.unkin.net/v1alpha1:
- ObjectStoreUser: creates an RGW user, delivers its key pair to a Secret
- Bucket: creates an S3 bucket owned by an ObjectStoreUser; owns the
  bucket's aggregate S3 policy (union of all BucketAccess grants)
- BucketAccess: grants read-only/read-write/full access, provisioning a
  dedicated user (or reusing a referenced one) and delivering RW/RO keys

The internal/ceph client wraps the dashboard /api/auth, /api/rgw/user and
/api/rgw/bucket endpoints with lazy token auth and re-auth on 401. Bucket
policies are rendered deterministically and applied via the bucket
policy API (Reef 18.2+). Credentials come from the cephrgw-credentials
Secret via env. Includes generated CRDs/RBAC, samples, kind manifests,
Woodpecker CI, and docs/ceph-setup.md covering the required Ceph
dashboard account, RGW wiring and permissions.
This commit is contained in:
benvin
2026-07-18 00:07:22 +10:00
commit 1ea1713d6e
41 changed files with 4455 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ObjectLockMode is the S3 object-lock retention mode.
// +kubebuilder:validation:Enum=GOVERNANCE;COMPLIANCE
type ObjectLockMode string
const (
ObjectLockGovernance ObjectLockMode = "GOVERNANCE"
ObjectLockCompliance ObjectLockMode = "COMPLIANCE"
)
// ObjectLock configures S3 object lock (WORM) on a bucket. Object lock can only
// be enabled at creation time and requires versioning.
type ObjectLock struct {
// Enabled turns on object lock for the bucket.
Enabled bool `json:"enabled"`
// Mode is the default retention mode applied to new objects.
// +optional
Mode ObjectLockMode `json:"mode,omitempty"`
// Days is the default retention period in days. Mutually exclusive with Years.
// +optional
Days *int32 `json:"days,omitempty"`
// Years is the default retention period in years. Mutually exclusive with Days.
// +optional
Years *int32 `json:"years,omitempty"`
}
// BucketSpec defines a Ceph RGW (S3) bucket owned by an ObjectStoreUser.
type BucketSpec struct {
// BucketName is the S3 bucket name. Defaults to metadata.name. Immutable.
// +optional
BucketName string `json:"bucketName,omitempty"`
// OwnerRef names the ObjectStoreUser (in this namespace) that owns the
// bucket. The owner always has full control; grant additional principals
// with BucketAccess objects.
OwnerRef string `json:"ownerRef"`
// Zonegroup optionally pins the bucket to a specific RGW zonegroup.
// +optional
Zonegroup string `json:"zonegroup,omitempty"`
// PlacementTarget optionally selects a non-default placement target/pool.
// +optional
PlacementTarget string `json:"placementTarget,omitempty"`
// Versioning enables S3 object versioning on the bucket.
// +optional
Versioning bool `json:"versioning,omitempty"`
// ObjectLock configures S3 object lock. Enabling it forces versioning on.
// +optional
ObjectLock *ObjectLock `json:"objectLock,omitempty"`
// Quota optionally applies a bucket-level quota.
// +optional
Quota *Quota `json:"quota,omitempty"`
// Tags are bucket tags (key/value) applied to the bucket.
// +optional
Tags map[string]string `json:"tags,omitempty"`
// RetainOnDelete keeps the RGW bucket (and its objects) when the Bucket
// resource is deleted. By default the operator removes the empty bucket;
// it never purges objects unless PurgeOnDelete is also set.
// +optional
RetainOnDelete bool `json:"retainOnDelete,omitempty"`
// PurgeOnDelete deletes the bucket together with all objects it contains
// when the Bucket resource is removed. Dangerous; defaults to false.
// +optional
PurgeOnDelete bool `json:"purgeOnDelete,omitempty"`
}
// BucketStatus reports observed bucket state.
type BucketStatus struct {
// Phase is a coarse lifecycle summary (Pending/Ready/Error).
// +optional
Phase string `json:"phase,omitempty"`
// BucketName is the provisioned S3 bucket name.
// +optional
BucketName string `json:"bucketName,omitempty"`
// BucketID is the RGW internal bucket instance id.
// +optional
BucketID string `json:"bucketID,omitempty"`
// Owner is the RGW uid that owns the bucket.
// +optional
Owner string `json:"owner,omitempty"`
// PolicyPrincipals is the number of extra principals granted via
// BucketAccess and reflected in the bucket policy.
// +optional
PolicyPrincipals int32 `json:"policyPrincipals,omitempty"`
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// +optional
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=bkt
// +kubebuilder:printcolumn:name="Bucket",type=string,JSONPath=`.status.bucketName`
// +kubebuilder:printcolumn:name="Owner",type=string,JSONPath=`.status.owner`
// +kubebuilder:printcolumn:name="Grants",type=integer,JSONPath=`.status.policyPrincipals`
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
// Bucket is a Ceph RGW S3 bucket.
type Bucket struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec BucketSpec `json:"spec,omitempty"`
Status BucketStatus `json:"status,omitempty"`
}
// +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{})
}
+101
View File
@@ -0,0 +1,101 @@
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// AccessLevel is the level of access a principal is granted to a bucket. The
// operator translates it into an S3 bucket policy statement.
// +kubebuilder:validation:Enum=read-only;read-write;full
type AccessLevel string
const (
// AccessReadOnly grants object GET and bucket LIST (s3:GetObject,
// s3:ListBucket and friends).
AccessReadOnly AccessLevel = "read-only"
// AccessReadWrite grants read plus object PUT/DELETE and multipart.
AccessReadWrite AccessLevel = "read-write"
// AccessFull grants s3:* on the bucket and its objects.
AccessFull AccessLevel = "full"
)
// BucketAccessSpec grants an RGW user a level of access to a Bucket by
// maintaining a statement in the bucket's S3 policy. If UserRef is empty the
// operator provisions a dedicated user for this grant and writes its keys into
// a Secret; otherwise it grants an existing ObjectStoreUser.
type BucketAccessSpec struct {
// BucketRef names the Bucket (in this namespace) to grant access to.
BucketRef string `json:"bucketRef"`
// Level is the access level to grant.
Level AccessLevel `json:"level"`
// UserRef optionally names an existing ObjectStoreUser (in this namespace)
// to grant. When set, the operator does not create or delete a user and
// SecretName is ignored (that user already owns its own credential Secret).
// +optional
UserRef string `json:"userRef,omitempty"`
// UID overrides the id of the dedicated user created when UserRef is empty.
// Defaults to "<bucket>-<name>". Ignored when UserRef is set.
// +optional
UID string `json:"uid,omitempty"`
// SecretName is the Secret the operator writes credentials into for the
// dedicated user it creates (UserRef empty). Defaults to "<name>-rgw".
// +optional
SecretName string `json:"secretName,omitempty"`
}
// BucketAccessStatus reports observed grant state.
type BucketAccessStatus struct {
// Phase is a coarse lifecycle summary (Pending/Ready/Error).
// +optional
Phase string `json:"phase,omitempty"`
// UID is the RGW user id that was granted access.
// +optional
UID string `json:"uid,omitempty"`
// SecretName is the Secret holding the dedicated user's credentials, if any.
// +optional
SecretName string `json:"secretName,omitempty"`
// Bound reports whether the grant is reflected in the bucket policy.
// +optional
Bound bool `json:"bound,omitempty"`
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// +optional
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=ba
// +kubebuilder:printcolumn:name="Bucket",type=string,JSONPath=`.spec.bucketRef`
// +kubebuilder:printcolumn:name="Level",type=string,JSONPath=`.spec.level`
// +kubebuilder:printcolumn:name="UID",type=string,JSONPath=`.status.uid`
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
// BucketAccess grants an RGW user read-only, read-write or full access to a
// Bucket via the bucket's S3 policy.
type BucketAccess struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec BucketAccessSpec `json:"spec,omitempty"`
Status BucketAccessStatus `json:"status,omitempty"`
}
// +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{})
}
+27
View File
@@ -0,0 +1,27 @@
package v1alpha1
// Quota describes an RGW quota applied to a user or a bucket. A nil limit (or a
// negative value) means unlimited for that dimension.
type Quota struct {
// Enabled turns the quota on. When false the other fields are ignored and
// the quota is disabled on the target.
// +kubebuilder:default=true
// +optional
Enabled bool `json:"enabled,omitempty"`
// MaxSizeBytes caps the total size in bytes. Nil or negative means unlimited.
// +optional
MaxSizeBytes *int64 `json:"maxSizeBytes,omitempty"`
// MaxObjects caps the number of objects. Nil or negative means unlimited.
// +optional
MaxObjects *int64 `json:"maxObjects,omitempty"`
}
// SecretKeyRef points at a single key within a Secret in the same namespace.
type SecretKeyRef struct {
// Name is the Secret name.
Name string `json:"name"`
// Key is the data key within the Secret.
Key string `json:"key"`
}
+3
View File
@@ -0,0 +1,3 @@
// +kubebuilder:object:generate=true
// +groupName=ceph.unkin.net
package v1alpha1
+17
View File
@@ -0,0 +1,17 @@
package v1alpha1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is the group/version used to register these objects.
GroupVersion = schema.GroupVersion{Group: "ceph.unkin.net", Version: "v1alpha1"}
// SchemeBuilder registers the API types with a runtime scheme.
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
+91
View File
@@ -0,0 +1,91 @@
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// ObjectStoreUserSpec defines a Ceph RGW (S3) user. The operator creates the
// user through the Ceph dashboard API and writes its generated access/secret
// key pair into a Kubernetes Secret. The key material is never stored on the
// resource itself.
type ObjectStoreUserSpec struct {
// UID is the RGW user id. Defaults to metadata.name. Immutable once created.
// +optional
UID string `json:"uid,omitempty"`
// DisplayName is the human-readable name for the user. Defaults to the UID.
// +optional
DisplayName string `json:"displayName,omitempty"`
// Email is an optional email address recorded on the user.
// +optional
Email string `json:"email,omitempty"`
// MaxBuckets caps how many buckets the user may own. A negative value
// disables bucket creation; 0 leaves the RGW default. Defaults to 1000.
// +kubebuilder:default=1000
// +optional
MaxBuckets *int32 `json:"maxBuckets,omitempty"`
// Suspended, when true, suspends the user so its keys stop working.
// +optional
Suspended bool `json:"suspended,omitempty"`
// Quota optionally applies a user-level quota.
// +optional
Quota *Quota `json:"quota,omitempty"`
// SecretName is the Secret the operator writes the access/secret key into.
// Defaults to "<name>-rgw". The Secret holds AWS_ACCESS_KEY_ID,
// AWS_SECRET_ACCESS_KEY, BUCKET_HOST and the RGW uid.
// +optional
SecretName string `json:"secretName,omitempty"`
}
// ObjectStoreUserStatus reports observed user state.
type ObjectStoreUserStatus struct {
// Phase is a coarse lifecycle summary (Pending/Ready/Error).
// +optional
Phase string `json:"phase,omitempty"`
// UID is the RGW user id that was provisioned.
// +optional
UID string `json:"uid,omitempty"`
// SecretName is the Secret holding the user's credentials.
// +optional
SecretName string `json:"secretName,omitempty"`
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// +optional
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=osu
// +kubebuilder:printcolumn:name="UID",type=string,JSONPath=`.status.uid`
// +kubebuilder:printcolumn:name="Secret",type=string,JSONPath=`.status.secretName`
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
// ObjectStoreUser is a Ceph RGW S3 user whose keys are delivered into a Secret.
type ObjectStoreUser struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ObjectStoreUserSpec `json:"spec,omitempty"`
Status ObjectStoreUserStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ObjectStoreUserList contains a list of ObjectStoreUser.
type ObjectStoreUserList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ObjectStoreUser `json:"items"`
}
func init() {
SchemeBuilder.Register(&ObjectStoreUser{}, &ObjectStoreUserList{})
}
+390
View File
@@ -0,0 +1,390 @@
//go:build !ignore_autogenerated
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha1
import (
"k8s.io/apimachinery/pkg/apis/meta/v1"
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 *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)
out.Spec = in.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 *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
}
// 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.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// 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 *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.ObjectLock != nil {
in, out := &in.ObjectLock, &out.ObjectLock
*out = new(ObjectLock)
(*in).DeepCopyInto(*out)
}
if in.Quota != nil {
in, out := &in.Quota, &out.Quota
*out = new(Quota)
(*in).DeepCopyInto(*out)
}
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*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 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.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// 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 *ObjectLock) DeepCopyInto(out *ObjectLock) {
*out = *in
if in.Days != nil {
in, out := &in.Days, &out.Days
*out = new(int32)
**out = **in
}
if in.Years != nil {
in, out := &in.Years, &out.Years
*out = new(int32)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectLock.
func (in *ObjectLock) DeepCopy() *ObjectLock {
if in == nil {
return nil
}
out := new(ObjectLock)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectStoreUser) DeepCopyInto(out *ObjectStoreUser) {
*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 ObjectStoreUser.
func (in *ObjectStoreUser) DeepCopy() *ObjectStoreUser {
if in == nil {
return nil
}
out := new(ObjectStoreUser)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ObjectStoreUser) 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 *ObjectStoreUserList) DeepCopyInto(out *ObjectStoreUserList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ObjectStoreUser, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStoreUserList.
func (in *ObjectStoreUserList) DeepCopy() *ObjectStoreUserList {
if in == nil {
return nil
}
out := new(ObjectStoreUserList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ObjectStoreUserList) 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 *ObjectStoreUserSpec) DeepCopyInto(out *ObjectStoreUserSpec) {
*out = *in
if in.MaxBuckets != nil {
in, out := &in.MaxBuckets, &out.MaxBuckets
*out = new(int32)
**out = **in
}
if in.Quota != nil {
in, out := &in.Quota, &out.Quota
*out = new(Quota)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStoreUserSpec.
func (in *ObjectStoreUserSpec) DeepCopy() *ObjectStoreUserSpec {
if in == nil {
return nil
}
out := new(ObjectStoreUserSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ObjectStoreUserStatus) DeepCopyInto(out *ObjectStoreUserStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectStoreUserStatus.
func (in *ObjectStoreUserStatus) DeepCopy() *ObjectStoreUserStatus {
if in == nil {
return nil
}
out := new(ObjectStoreUserStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Quota) DeepCopyInto(out *Quota) {
*out = *in
if in.MaxSizeBytes != nil {
in, out := &in.MaxSizeBytes, &out.MaxSizeBytes
*out = new(int64)
**out = **in
}
if in.MaxObjects != nil {
in, out := &in.MaxObjects, &out.MaxObjects
*out = new(int64)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Quota.
func (in *Quota) DeepCopy() *Quota {
if in == nil {
return nil
}
out := new(Quota)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *SecretKeyRef) DeepCopyInto(out *SecretKeyRef) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeyRef.
func (in *SecretKeyRef) DeepCopy() *SecretKeyRef {
if in == nil {
return nil
}
out := new(SecretKeyRef)
in.DeepCopyInto(out)
return out
}