diff --git a/api/v1alpha1/user_types.go b/api/v1alpha1/user_types.go
index faf317660..742f055d9 100644
--- a/api/v1alpha1/user_types.go
+++ b/api/v1alpha1/user_types.go
@@ -42,6 +42,18 @@ type UserResourceSpec struct {
// enabled defines whether a user is enabled or disabled
// +optional
Enabled *bool `json:"enabled,omitempty"`
+
+ // password is the password set for the user
+ // +optional
+ Password *PasswordSpec `json:"password,omitempty"`
+}
+
+// +kubebuilder:validation:MinProperties:=1
+// +kubebuilder:validation:MaxProperties:=1
+type PasswordSpec struct {
+ // secretRef is a reference to a Secret containing the password for this user.
+ // +optional
+ SecretRef *KubernetesNameRef `json:"secretRef,omitempty"`
}
// UserFilter defines an existing resource by its properties
@@ -81,4 +93,9 @@ type UserResourceStatus struct {
// enabled defines whether a user is enabled or disabled
// +optional
Enabled bool `json:"enabled,omitempty"`
+
+ // passwordExpiresAt filters the response based on expriing passwords.
+ // +kubebuilder:validation:MaxLength:=255
+ // +optional
+ PasswordExpiresAt string `json:"passwordExpiresAt,omitempty"`
}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 4bd75eca4..1ae2be5a7 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -2786,6 +2786,26 @@ func (in *NeutronStatusMetadata) DeepCopy() *NeutronStatusMetadata {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordSpec) DeepCopyInto(out *PasswordSpec) {
+ *out = *in
+ if in.SecretRef != nil {
+ in, out := &in.SecretRef, &out.SecretRef
+ *out = new(KubernetesNameRef)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordSpec.
+func (in *PasswordSpec) DeepCopy() *PasswordSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(PasswordSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Port) DeepCopyInto(out *Port) {
*out = *in
@@ -5924,6 +5944,11 @@ func (in *UserResourceSpec) DeepCopyInto(out *UserResourceSpec) {
*out = new(bool)
**out = **in
}
+ if in.Password != nil {
+ in, out := &in.Password, &out.Password
+ *out = new(PasswordSpec)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserResourceSpec.
diff --git a/cmd/models-schema/zz_generated.openapi.go b/cmd/models-schema/zz_generated.openapi.go
index 9250f4e36..49a18ab83 100644
--- a/cmd/models-schema/zz_generated.openapi.go
+++ b/cmd/models-schema/zz_generated.openapi.go
@@ -127,6 +127,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkSpec": schema_openstack_resource_controller_v2_api_v1alpha1_NetworkSpec(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NetworkStatus": schema_openstack_resource_controller_v2_api_v1alpha1_NetworkStatus(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.NeutronStatusMetadata": schema_openstack_resource_controller_v2_api_v1alpha1_NeutronStatusMetadata(ref),
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PasswordSpec": schema_openstack_resource_controller_v2_api_v1alpha1_PasswordSpec(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.Port": schema_openstack_resource_controller_v2_api_v1alpha1_Port(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortFilter": schema_openstack_resource_controller_v2_api_v1alpha1_PortFilter(ref),
"github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PortImport": schema_openstack_resource_controller_v2_api_v1alpha1_PortImport(ref),
@@ -5235,6 +5236,25 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_NeutronStatusMetadata(
}
}
+func schema_openstack_resource_controller_v2_api_v1alpha1_PasswordSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "secretRef": {
+ SchemaProps: spec.SchemaProps{
+ Description: "secretRef is a reference to a Secret containing the password for this user.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
func schema_openstack_resource_controller_v2_api_v1alpha1_Port(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -11393,9 +11413,17 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_UserResourceSpec(ref c
Format: "",
},
},
+ "password": {
+ SchemaProps: spec.SchemaProps{
+ Description: "password is the password set for the user",
+ Ref: ref("github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PasswordSpec"),
+ },
+ },
},
},
},
+ Dependencies: []string{
+ "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1.PasswordSpec"},
}
}
@@ -11441,6 +11469,13 @@ func schema_openstack_resource_controller_v2_api_v1alpha1_UserResourceStatus(ref
Format: "",
},
},
+ "passwordExpiresAt": {
+ SchemaProps: spec.SchemaProps{
+ Description: "passwordExpiresAt filters the response based on expriing passwords.",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
},
},
},
diff --git a/config/crd/bases/openstack.k-orc.cloud_users.yaml b/config/crd/bases/openstack.k-orc.cloud_users.yaml
index bc8835301..ec3101c1a 100644
--- a/config/crd/bases/openstack.k-orc.cloud_users.yaml
+++ b/config/crd/bases/openstack.k-orc.cloud_users.yaml
@@ -186,6 +186,18 @@ spec:
minLength: 1
pattern: ^[^,]+$
type: string
+ password:
+ description: password is the password set for the user
+ maxProperties: 1
+ minProperties: 1
+ properties:
+ secretRef:
+ description: secretRef is a reference to a Secret containing
+ the password for this user.
+ maxLength: 253
+ minLength: 1
+ type: string
+ type: object
type: object
required:
- cloudCredentialsRef
@@ -313,6 +325,11 @@ spec:
not be unique.
maxLength: 1024
type: string
+ passwordExpiresAt:
+ description: passwordExpiresAt filters the response based on expriing
+ passwords.
+ maxLength: 255
+ type: string
type: object
type: object
required:
diff --git a/config/samples/openstack_v1alpha1_user.yaml b/config/samples/openstack_v1alpha1_user.yaml
index 09067e614..d27169d30 100644
--- a/config/samples/openstack_v1alpha1_user.yaml
+++ b/config/samples/openstack_v1alpha1_user.yaml
@@ -1,12 +1,48 @@
---
apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Domain
+metadata:
+ name: user-sample
+spec:
+ cloudCredentialsRef:
+ cloudName: devstack-admin
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resource: {}
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
+kind: Project
+metadata:
+ name: user-sample
+spec:
+ cloudCredentialsRef:
+ cloudName: devstack-admin
+ secretName: openstack-clouds
+ managementPolicy: managed
+ resource: {}
+---
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: user-sample
+ type: Opaque
+ stringData:
+ password: "TestPassword"
+---
+apiVersion: openstack.k-orc.cloud/v1alpha1
kind: User
metadata:
name: user-sample
spec:
cloudCredentialsRef:
- cloudName: openstack-admin
+ cloudName: devstack-admin
secretName: openstack-clouds
managementPolicy: managed
resource:
- description: Sample User
+ name: user-sample
+ description: User sample
+ domainRef: user-sample
+ defaultProjectRef: user-sample
+ enabled: true
+ password:
+ secretRef: user-sample
\ No newline at end of file
diff --git a/internal/controllers/user/actuator.go b/internal/controllers/user/actuator.go
index 391205112..2d9c4338d 100644
--- a/internal/controllers/user/actuator.go
+++ b/internal/controllers/user/actuator.go
@@ -135,6 +135,27 @@ func (actuator userActuator) CreateResource(ctx context.Context, obj orcObjectPT
defaultProjectID = ptr.Deref(project.Status.ID, "")
}
}
+
+ var password string
+ if resource.Password != nil {
+ secret, secretReconcileStatus := dependency.FetchDependency(
+ ctx, actuator.k8sClient, obj.Namespace,
+ resource.Password.SecretRef, "Secret",
+ func(*corev1.Secret) bool { return true },
+ )
+ reconcileStatus = reconcileStatus.WithReconcileStatus(secretReconcileStatus)
+ if secretReconcileStatus == nil {
+ var ok bool
+ passwordBytes, ok := secret.Data["password"]
+ if !ok {
+ reconcileStatus = reconcileStatus.WithReconcileStatus(
+ progress.NewReconcileStatus().WithProgressMessage("Password secret does not contain \"password\" key"))
+ } else {
+ password = string(passwordBytes)
+ }
+ }
+ }
+
if needsReschedule, _ := reconcileStatus.NeedsReschedule(); needsReschedule {
return nil, reconcileStatus
}
@@ -144,6 +165,7 @@ func (actuator userActuator) CreateResource(ctx context.Context, obj orcObjectPT
DomainID: domainID,
Enabled: resource.Enabled,
DefaultProjectID: defaultProjectID,
+ Password: password,
}
osResource, err := actuator.osClient.CreateUser(ctx, createOpts)
diff --git a/internal/controllers/user/controller.go b/internal/controllers/user/controller.go
index 4e432c0c7..2f966f873 100644
--- a/internal/controllers/user/controller.go
+++ b/internal/controllers/user/controller.go
@@ -20,6 +20,7 @@ import (
"context"
"errors"
+ corev1 "k8s.io/api/core/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/controller"
@@ -86,6 +87,17 @@ var domainImportDependency = dependency.NewDependency[*orcv1alpha1.UserList, *or
},
)
+var passwordDependency = dependency.NewDependency[*orcv1alpha1.UserList, *corev1.Secret](
+ "spec.resource.password.secretRef",
+ func(user *orcv1alpha1.User) []string {
+ resource := user.Spec.Resource
+ if resource == nil || resource.Password == nil || resource.Password.SecretRef == nil {
+ return nil
+ }
+ return []string{string(*resource.Password.SecretRef)}
+ },
+)
+
// SetupWithManager sets up the controller with the Manager.
func (c userReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctrl.Manager, options controller.Options) error {
log := ctrl.LoggerFrom(ctx)
@@ -106,8 +118,14 @@ func (c userReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctr
return err
}
+ passwordWatchEventHandler, err := passwordDependency.WatchEventHandler(log, k8sClient)
+ if err != nil {
+ return err
+ }
+
builder := ctrl.NewControllerManagedBy(mgr).
WithOptions(options).
+ For(&orcv1alpha1.User{}).
Watches(&orcv1alpha1.Domain{}, domainWatchEventHandler,
builder.WithPredicates(predicates.NewBecameAvailable(log, &orcv1alpha1.Domain{})),
).
@@ -118,12 +136,14 @@ func (c userReconcilerConstructor) SetupWithManager(ctx context.Context, mgr ctr
Watches(&orcv1alpha1.Domain{}, domainImportWatchEventHandler,
builder.WithPredicates(predicates.NewBecameAvailable(log, &orcv1alpha1.Domain{})),
).
- For(&orcv1alpha1.User{})
+ // General watch on secrets.
+ Watches(&corev1.Secret{}, passwordWatchEventHandler)
if err := errors.Join(
domainDependency.AddToManager(ctx, mgr),
projectDependency.AddToManager(ctx, mgr),
domainImportDependency.AddToManager(ctx, mgr),
+ passwordDependency.AddToManager(ctx, mgr),
credentialsDependency.AddToManager(ctx, mgr),
credentials.AddCredentialsWatch(log, mgr.GetClient(), builder, credentialsDependency),
); err != nil {
diff --git a/internal/controllers/user/tests/user-create-full/00-create-resource.yaml b/internal/controllers/user/tests/user-create-full/00-create-resource.yaml
index 4df449bda..e4f5f132f 100644
--- a/internal/controllers/user/tests/user-create-full/00-create-resource.yaml
+++ b/internal/controllers/user/tests/user-create-full/00-create-resource.yaml
@@ -20,6 +20,14 @@ spec:
secretName: openstack-clouds
managementPolicy: managed
resource: {}
+---
+ apiVersion: v1
+ kind: Secret
+ metadata:
+ name: user-create-full
+ type: Opaque
+ stringData:
+ password: "TestPassword"
---
apiVersion: openstack.k-orc.cloud/v1alpha1
kind: User
@@ -35,4 +43,6 @@ spec:
description: User from "create full" test
domainRef: user-create-full
defaultProjectRef: user-create-full
- enabled: true
\ No newline at end of file
+ enabled: true
+ password:
+ secretRef: user-create-full
\ No newline at end of file
diff --git a/internal/controllers/user/tests/user-create-minimal/00-assert.yaml b/internal/controllers/user/tests/user-create-minimal/00-assert.yaml
index 950d429bd..02a409a8f 100644
--- a/internal/controllers/user/tests/user-create-minimal/00-assert.yaml
+++ b/internal/controllers/user/tests/user-create-minimal/00-assert.yaml
@@ -27,3 +27,5 @@ assertAll:
- celExpr: "!has(user.status.resource.description)"
- celExpr: "user.status.resource.domainID == 'default'"
- celExpr: "!has(user.status.resource.defaultProjectID)"
+ - celExpr: "!has(user.status.resource.passwordExpiresAt)"
+
diff --git a/internal/controllers/user/tests/user-dependency/01-create-dependencies.yaml b/internal/controllers/user/tests/user-dependency/01-create-dependencies.yaml
index 4a292db93..d47398d55 100644
--- a/internal/controllers/user/tests/user-dependency/01-create-dependencies.yaml
+++ b/internal/controllers/user/tests/user-dependency/01-create-dependencies.yaml
@@ -25,4 +25,12 @@ spec:
cloudName: openstack-admin
secretName: openstack-clouds
managementPolicy: managed
- resource: {}
\ No newline at end of file
+ resource: {}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: user-create-full
+type: Opaque
+stringData:
+ password: "TestPassword"
\ No newline at end of file
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/passwordspec.go b/pkg/clients/applyconfiguration/api/v1alpha1/passwordspec.go
new file mode 100644
index 000000000..4dd652577
--- /dev/null
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/passwordspec.go
@@ -0,0 +1,43 @@
+/*
+Copyright The ORC 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 applyconfiguration-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ apiv1alpha1 "github.com/k-orc/openstack-resource-controller/v2/api/v1alpha1"
+)
+
+// PasswordSpecApplyConfiguration represents a declarative configuration of the PasswordSpec type for use
+// with apply.
+type PasswordSpecApplyConfiguration struct {
+ SecretRef *apiv1alpha1.KubernetesNameRef `json:"secretRef,omitempty"`
+}
+
+// PasswordSpecApplyConfiguration constructs a declarative configuration of the PasswordSpec type for use with
+// apply.
+func PasswordSpec() *PasswordSpecApplyConfiguration {
+ return &PasswordSpecApplyConfiguration{}
+}
+
+// WithSecretRef sets the SecretRef field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the SecretRef field is set to the value of the last call.
+func (b *PasswordSpecApplyConfiguration) WithSecretRef(value apiv1alpha1.KubernetesNameRef) *PasswordSpecApplyConfiguration {
+ b.SecretRef = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/userresourcespec.go b/pkg/clients/applyconfiguration/api/v1alpha1/userresourcespec.go
index ed4b86a2e..e7898082e 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/userresourcespec.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/userresourcespec.go
@@ -25,11 +25,12 @@ import (
// UserResourceSpecApplyConfiguration represents a declarative configuration of the UserResourceSpec type for use
// with apply.
type UserResourceSpecApplyConfiguration struct {
- Name *apiv1alpha1.OpenStackName `json:"name,omitempty"`
- Description *string `json:"description,omitempty"`
- DomainRef *apiv1alpha1.KubernetesNameRef `json:"domainRef,omitempty"`
- DefaultProjectRef *apiv1alpha1.KubernetesNameRef `json:"defaultProjectRef,omitempty"`
- Enabled *bool `json:"enabled,omitempty"`
+ Name *apiv1alpha1.OpenStackName `json:"name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ DomainRef *apiv1alpha1.KubernetesNameRef `json:"domainRef,omitempty"`
+ DefaultProjectRef *apiv1alpha1.KubernetesNameRef `json:"defaultProjectRef,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+ Password *PasswordSpecApplyConfiguration `json:"password,omitempty"`
}
// UserResourceSpecApplyConfiguration constructs a declarative configuration of the UserResourceSpec type for use with
@@ -77,3 +78,11 @@ func (b *UserResourceSpecApplyConfiguration) WithEnabled(value bool) *UserResour
b.Enabled = &value
return b
}
+
+// WithPassword sets the Password field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the Password field is set to the value of the last call.
+func (b *UserResourceSpecApplyConfiguration) WithPassword(value *PasswordSpecApplyConfiguration) *UserResourceSpecApplyConfiguration {
+ b.Password = value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/api/v1alpha1/userresourcestatus.go b/pkg/clients/applyconfiguration/api/v1alpha1/userresourcestatus.go
index 05093ff79..c23b0b6cf 100644
--- a/pkg/clients/applyconfiguration/api/v1alpha1/userresourcestatus.go
+++ b/pkg/clients/applyconfiguration/api/v1alpha1/userresourcestatus.go
@@ -21,11 +21,12 @@ package v1alpha1
// UserResourceStatusApplyConfiguration represents a declarative configuration of the UserResourceStatus type for use
// with apply.
type UserResourceStatusApplyConfiguration struct {
- Name *string `json:"name,omitempty"`
- Description *string `json:"description,omitempty"`
- DomainID *string `json:"domainID,omitempty"`
- DefaultProjectID *string `json:"defaultProjectID,omitempty"`
- Enabled *bool `json:"enabled,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ DomainID *string `json:"domainID,omitempty"`
+ DefaultProjectID *string `json:"defaultProjectID,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+ PasswordExpiresAt *string `json:"passwordExpiresAt,omitempty"`
}
// UserResourceStatusApplyConfiguration constructs a declarative configuration of the UserResourceStatus type for use with
@@ -73,3 +74,11 @@ func (b *UserResourceStatusApplyConfiguration) WithEnabled(value bool) *UserReso
b.Enabled = &value
return b
}
+
+// WithPasswordExpiresAt sets the PasswordExpiresAt field in the declarative configuration to the given value
+// and returns the receiver, so that objects can be built by chaining "With" function invocations.
+// If called multiple times, the PasswordExpiresAt field is set to the value of the last call.
+func (b *UserResourceStatusApplyConfiguration) WithPasswordExpiresAt(value string) *UserResourceStatusApplyConfiguration {
+ b.PasswordExpiresAt = &value
+ return b
+}
diff --git a/pkg/clients/applyconfiguration/internal/internal.go b/pkg/clients/applyconfiguration/internal/internal.go
index 216436517..8f33f6ae4 100644
--- a/pkg/clients/applyconfiguration/internal/internal.go
+++ b/pkg/clients/applyconfiguration/internal/internal.go
@@ -1450,6 +1450,12 @@ var schemaYAML = typed.YAMLObject(`types:
- name: resource
type:
namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.NetworkResourceStatus
+- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.PasswordSpec
+ map:
+ fields:
+ - name: secretRef
+ type:
+ scalar: string
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.Port
map:
fields:
@@ -3409,6 +3415,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: name
type:
scalar: string
+ - name: password
+ type:
+ namedType: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.PasswordSpec
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.UserResourceStatus
map:
fields:
@@ -3427,6 +3436,9 @@ var schemaYAML = typed.YAMLObject(`types:
- name: name
type:
scalar: string
+ - name: passwordExpiresAt
+ type:
+ scalar: string
- name: com.github.k-orc.openstack-resource-controller.v2.api.v1alpha1.UserSpec
map:
fields:
diff --git a/pkg/clients/applyconfiguration/utils.go b/pkg/clients/applyconfiguration/utils.go
index bb76ee624..605bc9ace 100644
--- a/pkg/clients/applyconfiguration/utils.go
+++ b/pkg/clients/applyconfiguration/utils.go
@@ -208,6 +208,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &apiv1alpha1.NetworkStatusApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("NeutronStatusMetadata"):
return &apiv1alpha1.NeutronStatusMetadataApplyConfiguration{}
+ case v1alpha1.SchemeGroupVersion.WithKind("PasswordSpec"):
+ return &apiv1alpha1.PasswordSpecApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("Port"):
return &apiv1alpha1.PortApplyConfiguration{}
case v1alpha1.SchemeGroupVersion.WithKind("PortFilter"):
diff --git a/website/docs/crd-reference.md b/website/docs/crd-reference.md
index 2513429b8..6529bc4de 100644
--- a/website/docs/crd-reference.md
+++ b/website/docs/crd-reference.md
@@ -1925,6 +1925,7 @@ _Appears in:_
- [HostID](#hostid)
- [NetworkFilter](#networkfilter)
- [NetworkResourceSpec](#networkresourcespec)
+- [PasswordSpec](#passwordspec)
- [PortFilter](#portfilter)
- [PortResourceSpec](#portresourcespec)
- [RoleFilter](#rolefilter)
@@ -2363,6 +2364,24 @@ _Appears in:_
+#### PasswordSpec
+
+
+
+
+
+_Validation:_
+- MaxProperties: 1
+- MinProperties: 1
+
+_Appears in:_
+- [UserResourceSpec](#userresourcespec)
+
+| Field | Description | Default | Validation |
+| --- | --- | --- | --- |
+| `secretRef` _[KubernetesNameRef](#kubernetesnameref)_ | secretRef is a reference to a Secret containing the password for this user. | | MaxLength: 253
MinLength: 1
|
+
+
#### Port
@@ -4436,6 +4455,7 @@ _Appears in:_
| `domainRef` _[KubernetesNameRef](#kubernetesnameref)_ | domainRef is a reference to the ORC Domain which this resource is associated with. | | MaxLength: 253
MinLength: 1
|
| `defaultProjectRef` _[KubernetesNameRef](#kubernetesnameref)_ | defaultProjectRef is a reference to the Default Project which this resource is associated with. | | MaxLength: 253
MinLength: 1
|
| `enabled` _boolean_ | enabled defines whether a user is enabled or disabled | | |
+| `password` _[PasswordSpec](#passwordspec)_ | password is the password set for the user | | MaxProperties: 1
MinProperties: 1
|
#### UserResourceStatus
@@ -4456,6 +4476,7 @@ _Appears in:_
| `domainID` _string_ | domainID is the ID of the Domain to which the resource is associated. | | MaxLength: 1024
|
| `defaultProjectID` _string_ | defaultProjectID is the ID of the Default Project to which the user is associated with. | | MaxLength: 1024
|
| `enabled` _boolean_ | enabled defines whether a user is enabled or disabled | | |
+| `passwordExpiresAt` _string_ | passwordExpiresAt filters the response based on expriing passwords. | | MaxLength: 255
|
#### UserSpec