From 1915cfaaf7fd97c8713d28713e1604edfa60a1ff Mon Sep 17 00:00:00 2001 From: cc-datum Date: Wed, 29 Oct 2025 01:34:32 -0600 Subject: [PATCH 1/5] feat: add display name and title fields to user preferences --- .gitignore | 3 +++ .../crd/bases/iam/iam.miloapis.com_userpreferences.yaml | 6 ++++++ config/samples/iam/v1alpha1/userpreference.yaml | 4 +++- internal/webhooks/iam/v1alpha1/user_webhook.go | 4 +++- pkg/apis/iam/v1alpha1/userpreference_types.go | 8 ++++++++ 5 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c9b29b6b..decb854e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,6 @@ vendor/ # Files used by the taskfile. .task +# JetBrains IDEs +.idea/ +.run/ \ No newline at end of file diff --git a/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml b/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml index e9338953..be539d34 100644 --- a/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml +++ b/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml @@ -52,6 +52,9 @@ spec: spec: description: UserPreferenceSpec defines the desired state of UserPreference properties: + displayName: + description: DisplayName is the user's preferred display name. + type: string theme: default: system description: The user's theme preference. @@ -60,6 +63,9 @@ spec: - dark - system type: string + title: + description: Title is the user's title or role. + type: string userRef: description: Reference to the user these preferences belong to. properties: diff --git a/config/samples/iam/v1alpha1/userpreference.yaml b/config/samples/iam/v1alpha1/userpreference.yaml index f1452b5f..5a45e2b3 100644 --- a/config/samples/iam/v1alpha1/userpreference.yaml +++ b/config/samples/iam/v1alpha1/userpreference.yaml @@ -5,4 +5,6 @@ metadata: spec: userRef: name: user-sample - theme: "dark" \ No newline at end of file + theme: "dark" + displayName: my display name + title: my title \ No newline at end of file diff --git a/internal/webhooks/iam/v1alpha1/user_webhook.go b/internal/webhooks/iam/v1alpha1/user_webhook.go index eeadf62e..60f1f9fc 100644 --- a/internal/webhooks/iam/v1alpha1/user_webhook.go +++ b/internal/webhooks/iam/v1alpha1/user_webhook.go @@ -134,7 +134,9 @@ func (v *UserValidator) createUserPreference(ctx context.Context, user *iamv1alp UserRef: iamv1alpha1.UserReference{ Name: user.Name, }, - Theme: "system", // Default theme + Theme: "system", // Default theme + DisplayName: "", + Title: "", }, } diff --git a/pkg/apis/iam/v1alpha1/userpreference_types.go b/pkg/apis/iam/v1alpha1/userpreference_types.go index c47feb11..9e8e8b32 100644 --- a/pkg/apis/iam/v1alpha1/userpreference_types.go +++ b/pkg/apis/iam/v1alpha1/userpreference_types.go @@ -32,6 +32,14 @@ type UserPreferenceSpec struct { // +kubebuilder:validation:Optional // +kubebuilder:default=system Theme string `json:"theme,omitempty"` + + // DisplayName is the user's preferred display name. + // +kubebuilder:validation:Optional + DisplayName string `json:"displayName,omitempty"` + + // Title is the user's title or role. + // +kubebuilder:validation:Optional + Title string `json:"title,omitempty"` } // UserPreferenceStatus defines the observed state of UserPreference From 78284b112f2f5204ef45aefafcb94feffab7568e Mon Sep 17 00:00:00 2001 From: cc-datum Date: Wed, 29 Oct 2025 15:08:29 -0600 Subject: [PATCH 2/5] docs: for pull #382, fixed 1 outdated doc(s) --- docs/api/iam.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/api/iam.md b/docs/api/iam.md index 02560446..49a56c1a 100644 --- a/docs/api/iam.md +++ b/docs/api/iam.md @@ -2597,6 +2597,20 @@ UserPreferenceSpec defines the desired state of UserPreference Default: system
false + + displayName + string + + DisplayName is the user's preferred display name.
+ + false + + title + string + + Title is the user's title or role.
+ + false From bb9f68803c3f48986064d0fc895093fb00004564 Mon Sep 17 00:00:00 2001 From: cc-datum Date: Wed, 29 Oct 2025 19:46:52 -0600 Subject: [PATCH 3/5] feat: add timezone to user preferences --- cmd/milo/controller-manager/controllermanager.go | 12 +++++++++--- .../iam/iam.miloapis.com_userpreferences.yaml | 3 +++ pkg/apis/iam/v1alpha1/userpreference_types.go | 16 ++++++++++------ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/cmd/milo/controller-manager/controllermanager.go b/cmd/milo/controller-manager/controllermanager.go index fd689df7..72c6527e 100644 --- a/cmd/milo/controller-manager/controllermanager.go +++ b/cmd/milo/controller-manager/controllermanager.go @@ -240,6 +240,9 @@ func NewCommand() *cobra.Command { fs.StringVar(&AssignableRolesNamespace, "assignable-roles-namespace", "datum-cloud", "An extra namespace that the system allows to be used for assignable roles.") + // Leader election flags + cmd.Flags().StringVar(&s.LeaderElection.Namespace, "leader-election-namespace", "datum-system", "The namespace in which the leader election resource will be created. If empty, uses the current namespace.") + s.InfraCluster.AddFlags(namedFlagSets.FlagSet("Infrastructure Cluster")) s.ControlPlane.AddFlags(namedFlagSets.FlagSet("Control Plane")) @@ -270,8 +273,11 @@ func ResyncPeriod(c *config.CompletedConfig) func() time.Duration { type Options struct { *options.KubeControllerManagerOptions - InfraCluster *infracluster.Options - ControlPlane *controlplane.Options + InfraCluster *infracluster.Options + ControlPlane *controlplane.Options + LeaderElection struct { + Namespace string + } // The port to use for the controller-runtime webhook server. ControllerRuntimeWebhookPort int @@ -669,7 +675,7 @@ func Run(ctx context.Context, c *config.CompletedConfig, opts *Options) error { // Start lease candidate controller for coordinated leader election leaseCandidate, waitForSync, err := leaderelection.NewCandidate( c.Client, - "datum-system", + opts.LeaderElection.Namespace, id, "datum-controller-manager", binaryVersion.FinalizeVersion(), diff --git a/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml b/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml index be539d34..36fcf880 100644 --- a/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml +++ b/config/crd/bases/iam/iam.miloapis.com_userpreferences.yaml @@ -63,6 +63,9 @@ spec: - dark - system type: string + timeZone: + description: The user's time zone preference. + type: string title: description: Title is the user's title or role. type: string diff --git a/pkg/apis/iam/v1alpha1/userpreference_types.go b/pkg/apis/iam/v1alpha1/userpreference_types.go index 9e8e8b32..5317d1eb 100644 --- a/pkg/apis/iam/v1alpha1/userpreference_types.go +++ b/pkg/apis/iam/v1alpha1/userpreference_types.go @@ -27,12 +27,6 @@ type UserPreferenceSpec struct { // +kubebuilder:validation:Required UserRef UserReference `json:"userRef"` - // The user's theme preference. - // +kubebuilder:validation:Enum=light;dark;system - // +kubebuilder:validation:Optional - // +kubebuilder:default=system - Theme string `json:"theme,omitempty"` - // DisplayName is the user's preferred display name. // +kubebuilder:validation:Optional DisplayName string `json:"displayName,omitempty"` @@ -40,6 +34,16 @@ type UserPreferenceSpec struct { // Title is the user's title or role. // +kubebuilder:validation:Optional Title string `json:"title,omitempty"` + + // The user's theme preference. + // +kubebuilder:validation:Enum=light;dark;system + // +kubebuilder:validation:Optional + // +kubebuilder:default=system + Theme string `json:"theme,omitempty"` + + // The user's time zone preference. + // +kubebuilder:validation:Optional' + TimeZone string `json:"timeZone,omitempty"` } // UserPreferenceStatus defines the observed state of UserPreference From 0a7648b48b731e8f2e5f353407011c0942e232c0 Mon Sep 17 00:00:00 2001 From: cc-datum Date: Wed, 29 Oct 2025 20:14:50 -0600 Subject: [PATCH 4/5] docs: for pull #382, fixed 1 outdated doc(s) --- docs/api/iam.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/api/iam.md b/docs/api/iam.md index 49a56c1a..549fa39d 100644 --- a/docs/api/iam.md +++ b/docs/api/iam.md @@ -2611,6 +2611,13 @@ UserPreferenceSpec defines the desired state of UserPreference Title is the user's title or role.
false + + timeZone + string + + The user's time zone preference.
+ + false From a31a28141d09959ca24bd7db185bef9d1d3eef3d Mon Sep 17 00:00:00 2001 From: cc-datum Date: Thu, 30 Oct 2025 01:54:34 -0600 Subject: [PATCH 5/5] feat: add leader election candidate namespace support --- cmd/milo/controller-manager/controllermanager.go | 15 ++++++--------- config/controller-manager/base/deployment.yaml | 3 +++ internal/infra-cluster/client.go | 7 +++++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cmd/milo/controller-manager/controllermanager.go b/cmd/milo/controller-manager/controllermanager.go index 72c6527e..b5fdbbba 100644 --- a/cmd/milo/controller-manager/controllermanager.go +++ b/cmd/milo/controller-manager/controllermanager.go @@ -240,9 +240,6 @@ func NewCommand() *cobra.Command { fs.StringVar(&AssignableRolesNamespace, "assignable-roles-namespace", "datum-cloud", "An extra namespace that the system allows to be used for assignable roles.") - // Leader election flags - cmd.Flags().StringVar(&s.LeaderElection.Namespace, "leader-election-namespace", "datum-system", "The namespace in which the leader election resource will be created. If empty, uses the current namespace.") - s.InfraCluster.AddFlags(namedFlagSets.FlagSet("Infrastructure Cluster")) s.ControlPlane.AddFlags(namedFlagSets.FlagSet("Control Plane")) @@ -273,11 +270,8 @@ func ResyncPeriod(c *config.CompletedConfig) func() time.Duration { type Options struct { *options.KubeControllerManagerOptions - InfraCluster *infracluster.Options - ControlPlane *controlplane.Options - LeaderElection struct { - Namespace string - } + InfraCluster *infracluster.Options + ControlPlane *controlplane.Options // The port to use for the controller-runtime webhook server. ControllerRuntimeWebhookPort int @@ -294,6 +288,9 @@ func NewOptions() (*Options, error) { KubeControllerManagerOptions: baseOpts, InfraCluster: &infracluster.Options{ KubeconfigFile: baseOpts.Generic.ClientConnection.Kubeconfig, + LeaderElection: &infracluster.LeaderElectionConfig{ + CandidateNamespace: "datum-system", + }, }, ControlPlane: &controlplane.Options{}, } @@ -675,7 +672,7 @@ func Run(ctx context.Context, c *config.CompletedConfig, opts *Options) error { // Start lease candidate controller for coordinated leader election leaseCandidate, waitForSync, err := leaderelection.NewCandidate( c.Client, - opts.LeaderElection.Namespace, + opts.InfraCluster.LeaderElection.CandidateNamespace, id, "datum-controller-manager", binaryVersion.FinalizeVersion(), diff --git a/config/controller-manager/base/deployment.yaml b/config/controller-manager/base/deployment.yaml index bf919b7b..18e801bb 100644 --- a/config/controller-manager/base/deployment.yaml +++ b/config/controller-manager/base/deployment.yaml @@ -31,6 +31,7 @@ spec: - --leader-elect-renew-deadline=10s - --leader-elect-retry-period=2s - --leader-elect-resource-namespace=$(LEADER_ELECT_RESOURCE_NAMESPACE) + - --leader-election-candidate-namespace=$(LEADER_ELECTION_CANDIDATE_NAMESPACE) - --authentication-skip-lookup - --client-ca-file=$(CLIENT_CA_FILE) - --secure-port=6443 @@ -45,6 +46,8 @@ spec: env: - name: LEADER_ELECT_RESOURCE_NAMESPACE value: milo-system + - name: LEADER_ELECTION_CANDIDATE_NAMESPACE + value: datum-system # Default to INFO level logging - name: LOG_LEVEL value: "4" diff --git a/internal/infra-cluster/client.go b/internal/infra-cluster/client.go index 2b1cb584..2c12ece2 100644 --- a/internal/infra-cluster/client.go +++ b/internal/infra-cluster/client.go @@ -8,14 +8,21 @@ import ( "k8s.io/client-go/tools/clientcmd" ) +type LeaderElectionConfig struct { + CandidateNamespace string +} + // Options defines the configuration options available for modifying the // behavior of the infrastructure cluster client. type Options struct { KubeconfigFile string + LeaderElection *LeaderElectionConfig } func (o *Options) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.KubeconfigFile, "infra-cluster-kubeconfig", "-", "The path to the kubeconfig file for the infrastructure cluster. Use '-' to use the in-cluster config.") + fs.StringVar(&o.LeaderElection.CandidateNamespace, "leader-election-candidate-namespace", o.LeaderElection.CandidateNamespace, "The candidate namespace in which the leader election will be created.") + } func (o *Options) GetClient() (*rest.Config, error) {