diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index c20c87a46d1843b09f4126e1de18da1ca7930242..e49183f8e9acdf181f1c50162529990fa3f5f95d 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -28,7 +28,8 @@ spec: imagePullPolicy: Always args: - -namespace={{ .Release.Namespace }} - - -virtual-hosts-secret-name={{ .Values.virtualHostsSecretName }} + - -virtual-hosts-secret-prefix-name={{ .Values.virtualHostsSecretPrefixName }} + - -virtual-hosts-secret-count={{ .Values.virtualHostsSecretCount }} - -gitlab-pages-url={{ .Values.gitlabPagesURL }} - -auth-proxy-service-name={{ .Values.authProxyServiceName }} - -auth-proxy-service-port={{ .Values.authProxyServicePort }} diff --git a/controllers/controller_test.go b/controllers/controller_test.go index 143bdd1b6524cb69c4ca416aa21dc9f94d7ead2a..c53b35bab797c3aeb79c40d49adc5fbea5bc6cba 100644 --- a/controllers/controller_test.go +++ b/controllers/controller_test.go @@ -138,8 +138,9 @@ var _ = Describe("GitlabPagesSite controller", func() { gpsSite.Status.Conditions[0].Status == metav1.ConditionTrue }, timeout, interval).Should(BeTrue()) + vHostSecretName := getHttpdVHostSecretName(vHostsSecretPrefix, gpsSite.Name, vHostsSecretCount) httpdSecret := &corev1.Secret{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: vHostsSecretName, Namespace: operatorNamespace}, httpdSecret) + err := k8sClient.Get(ctx, types.NamespacedName{Name: vHostSecretName, Namespace: operatorNamespace}, httpdSecret) httpdConfiguration := string(httpdSecret.Data[generateSecretKey(gpsSite)]) Expect(err).ShouldNot(HaveOccurred()) @@ -189,8 +190,9 @@ var _ = Describe("GitlabPagesSite controller", func() { gpsSite.Status.Conditions[0].Status == metav1.ConditionTrue }, timeout, interval).Should(BeTrue()) + vHostSecretName := getHttpdVHostSecretName(vHostsSecretPrefix, gpsSite.Name, vHostsSecretCount) httpdSecret := &corev1.Secret{} - err := k8sClient.Get(ctx, types.NamespacedName{Name: vHostsSecretName, Namespace: operatorNamespace}, httpdSecret) + err := k8sClient.Get(ctx, types.NamespacedName{Name: vHostSecretName, Namespace: operatorNamespace}, httpdSecret) httpdConfiguration := string(httpdSecret.Data[generateSecretKey(gpsSite)]) Expect(err).ShouldNot(HaveOccurred()) @@ -435,5 +437,16 @@ var _ = Describe("GitlabPagesSite controller", func() { Expect(k8sClient.Get(ctx, types.NamespacedName{Name: routeName, Namespace: operatorNamespace}, route)).Should(Succeed()) Expect(route.Annotations["haproxy.router.openshift.io/ip_whitelist"]).To(Equal("example-ip-whitelist")) }) + + It("Create a secret name that matches prefix + a random number never bigger than limit", func() { + Expect(getHttpdVHostSecretName("secret-prefix", "my-website", 1)).To(Equal("secret-prefix-0")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-0", 2)).To(Equal("secret-prefix-1")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-1", 2)).To(Equal("secret-prefix-0")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-2", 2)).To(Equal("secret-prefix-1")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-3", 2)).To(Equal("secret-prefix-0")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-4", 2)).To(Equal("secret-prefix-1")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-5", 2)).To(Equal("secret-prefix-0")) + Expect(getHttpdVHostSecretName("secret-prefix", "my-website-6", 2)).To(Equal("secret-prefix-1")) + }) }) }) diff --git a/controllers/gitlabpagessite_controller.go b/controllers/gitlabpagessite_controller.go index c9a5c88ff10970f72ca29a8d2a77e7a640cb44f4..3ac8effb90e36e8d066c9d529531dde062f47cb3 100644 --- a/controllers/gitlabpagessite_controller.go +++ b/controllers/gitlabpagessite_controller.go @@ -19,6 +19,7 @@ package controllers import ( "context" "regexp" + "strconv" "strings" "github.com/go-logr/logr" @@ -55,17 +56,18 @@ const forceIpWhitelistNamespaceAnnotation = "webeos.webservices.cern.ch/force-ip // GitlabPagesSiteReconciler reconciles a GitlabPagesSite object type GitlabPagesSiteReconciler struct { client.Client - Scheme *runtime.Scheme - Namespace string - VirtualHostsSecretName string - GitlabPagesURL string - AuthProxyServiceName string - AuthProxyServicePort int - OIDCReturnPath string - RouterShardLabel string - DefaultRouterShard string - SharedSubdomainRegex *regexp.Regexp - logger logr.Logger + Scheme *runtime.Scheme + Namespace string + VirtualHostsSecretPrefixName string + GitlabPagesURL string + AuthProxyServiceName string + AuthProxyServicePort int + VirtualHostsSecretCount int + OIDCReturnPath string + RouterShardLabel string + DefaultRouterShard string + SharedSubdomainRegex *regexp.Regexp + logger logr.Logger } //+kubebuilder:rbac:groups=staticsites.webservices.cern.ch,resources=gitlabpagessites,verbs=get;list;watch;create;update;patch;delete @@ -114,11 +116,11 @@ func (r *GitlabPagesSiteReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, nil } - // Secret holding extra httpd configuration + // Secret holding the httpd configuration httpdVHostSecret := &v1.Secret{ ObjectMeta: metav1.ObjectMeta{ Namespace: r.Namespace, - Name: r.VirtualHostsSecretName, + Name: getHttpdVHostSecretName(r.VirtualHostsSecretPrefixName, gitlabPagesSite.Name, r.VirtualHostsSecretCount), }, } @@ -170,7 +172,7 @@ func (r *GitlabPagesSiteReconciler) Reconcile(ctx context.Context, req ctrl.Requ err = r.ensureGitlabPagesSiteHttpdConfig(ctx, gitlabPagesSite, httpdVHostSecret, oidcSecret) if err != nil { - r.logger.Error(err, "There was a problem while generating httpd config for the GitlabPagesSite") + r.logger.Error(err, "There was a problem while generating httpd config for the GitlabPagesSite for "+gitlabPagesSite.Name+" "+gitlabPagesSite.Namespace+" in "+getHttpdVHostSecretName(r.VirtualHostsSecretPrefixName, gitlabPagesSite.Name, r.VirtualHostsSecretCount)) return ctrl.Result{}, err } @@ -203,6 +205,29 @@ func (r *GitlabPagesSiteReconciler) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, nil } +// getHttpdVHostSecretName generates a consistent secret name for the httpd configuration +// +// Parameters: +// - prefix (string): The prefix for the secret name. +// - website (string): The input string for which the consistent integer value is computed. +// - limit (int): The upper bound (inclusive) of the range for the returned value. +// +// Returns: +// - name: A consistent secret name formed by prefix-{inteber between 0 and limit}. +// +func getHttpdVHostSecretName(prefix string, website string, limit int) string { + if limit <= 0 { + panic("max must be greater than 0") + } + sum := 0 + for _, char := range website { + sum += int(char) + } + value := sum % limit + + return strings.Join([]string{prefix, "-", strconv.Itoa(value)}, "") +} + // SetupWithManager sets up the controller with the Manager. func (r *GitlabPagesSiteReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 4dbc513f460e579a48eed2332406c10c806cfc40..c3add67c3c9ee908109d02456f846563054a3cd9 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -43,7 +43,8 @@ import ( // const variables used to initialize the Reconciler (they are also needed in the controller_test.go) const ( operatorNamespace = "default" - vHostsSecretName = "httpd-secret" + vHostsSecretPrefix = "httpd-secret" + vHostsSecretCount = 10 authProxyServiceName = "service-name" authProxyServicePort = 8080 routerShardLabel = "selected-router-shard-label" @@ -263,16 +264,17 @@ var _ = BeforeSuite(func() { Expect(err).ToNot(HaveOccurred()) err = (&GitlabPagesSiteReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Namespace: operatorNamespace, - VirtualHostsSecretName: vHostsSecretName, - AuthProxyServiceName: authProxyServiceName, - AuthProxyServicePort: authProxyServicePort, - RouterShardLabel: routerShardLabel, - DefaultRouterShard: defaultRouterShard, - OIDCReturnPath: oidcReturnPath, - SharedSubdomainRegex: domainRegex, + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Namespace: operatorNamespace, + VirtualHostsSecretPrefixName: vHostsSecretPrefix, + VirtualHostsSecretCount: vHostsSecretCount, + AuthProxyServiceName: authProxyServiceName, + AuthProxyServicePort: authProxyServicePort, + RouterShardLabel: routerShardLabel, + DefaultRouterShard: defaultRouterShard, + OIDCReturnPath: oidcReturnPath, + SharedSubdomainRegex: domainRegex, }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) diff --git a/main.go b/main.go index b8ffcc4e720b6e777861552f53e59d268e183745..81f9d54f53ad55f848e1a1aead8a207315922208 100644 --- a/main.go +++ b/main.go @@ -59,7 +59,8 @@ func main() { var metricsAddr string var enableLeaderElection bool var probeAddr string - var virtualHostsSecretName string + var virtualHostsSecretPrefixName string + var virtualHostsSecretCount int var namespace string var gitlabPagesURL string var authProxyServiceName string @@ -76,7 +77,8 @@ func main() { flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") flag.StringVar(&namespace, "namespace", "", "The name of the namespace where this operator is running. "+ "It will be also used when fetching objects required to proper functioning of the operator (virtual-hosts Secret, auth-proxy Service).") - flag.StringVar(&virtualHostsSecretName, "virtual-hosts-secret-name", "", "The name of the Secret where httpd configuration should be stored.") + flag.StringVar(&virtualHostsSecretPrefixName, "virtual-hosts-secret-prefix-name", "", "The prefix name of the Secrets where httpd configuration should be stored.") + flag.IntVar(&virtualHostsSecretCount, "virtual-hosts-secret-count", 10, "The number of secrets to be used to store httpd configuration.") flag.StringVar(&gitlabPagesURL, "gitlab-pages-url", "", "The URL of the gitlab pages webserver.") flag.StringVar(&authProxyServiceName, "auth-proxy-service-name", "", "The name of the service which exposes authenticating proxy.") flag.IntVar(&authProxyServicePort, "auth-proxy-service-port", 8080, "The port of the service which exposes authenticating proxy. Routes will use this value as their targetPort.") @@ -99,8 +101,8 @@ func main() { os.Exit(1) } - if len(virtualHostsSecretName) == 0 { - setupLog.Error(errors.New("missing required arguments"), "-virtual-hosts-secret-name is required") + if len(virtualHostsSecretPrefixName) == 0 { + setupLog.Error(errors.New("missing required arguments"), "-virtual-hosts-secret-prefix-name is required") os.Exit(1) } @@ -146,17 +148,18 @@ func main() { } if err = (&controllers.GitlabPagesSiteReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - VirtualHostsSecretName: virtualHostsSecretName, - Namespace: namespace, - GitlabPagesURL: gitlabPagesURL, - AuthProxyServiceName: authProxyServiceName, - AuthProxyServicePort: authProxyServicePort, - OIDCReturnPath: oidcReturnPath, - RouterShardLabel: routerShardLabel, - DefaultRouterShard: defaultRouterShard, - SharedSubdomainRegex: domainRegex, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + VirtualHostsSecretPrefixName: virtualHostsSecretPrefixName, + VirtualHostsSecretCount: virtualHostsSecretCount, + Namespace: namespace, + GitlabPagesURL: gitlabPagesURL, + AuthProxyServiceName: authProxyServiceName, + AuthProxyServicePort: authProxyServicePort, + OIDCReturnPath: oidcReturnPath, + RouterShardLabel: routerShardLabel, + DefaultRouterShard: defaultRouterShard, + SharedSubdomainRegex: domainRegex, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "GitlabPagesSite") os.Exit(1)