Skip to content
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ func main() {
Client: client,
Scheme: mgr.GetScheme(),
DisableDefaultInstall: strings.ToLower(os.Getenv(common.DisableDefaultInstallEnvVar)) == "true",
TLSMinVersion: string(profile.MinTLSVersion),
TLSCiphers: profile.Ciphers,
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "GitopsService")
os.Exit(1)
Expand Down
93 changes: 82 additions & 11 deletions controllers/consoleplugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ package controllers

import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
"reflect"
"sort"
"strings"

argocommon "github.com/argoproj-labs/argocd-operator/common"
argocdutil "github.com/argoproj-labs/argocd-operator/controllers/argoutil"
Expand Down Expand Up @@ -240,18 +244,52 @@ func securityContextForPlugin() *corev1.SecurityContext {
}
}

var httpdConfig = fmt.Sprintf(`LoadModule ssl_module modules/mod_ssl.so
func TLSVersionToPlugin(tlsVersion string) string {
versionMap := map[string]string{
"VersionTLS12": "TLSv1.2",
"VersionTLS13": "TLSv1.3",
"VersionTLS11": "TLSv1.1",
"VersionTLS10": "TLSv1",
}
if v, ok := versionMap[tlsVersion]; ok {
return v
}
return "" // default fallback
}

// buildHttpdConfig generates httpd.conf with dynamic TLS settings
func (r *ReconcileGitopsService) buildHttpdConfig() string {
httpdConfigBase := fmt.Sprintf(`LoadModule ssl_module modules/mod_ssl.so
Listen %d https
ServerRoot "/etc/httpd"

<VirtualHost *:%d>
DocumentRoot /var/www/html/plugin
SSLEngine on
SSLCertificateFile "/etc/httpd-ssl/certs/tls.crt"
SSLCertificateKeyFile "/etc/httpd-ssl/private/tls.key"
</VirtualHost>`, servicePort, servicePort)
SSLCertificateKeyFile "/etc/httpd-ssl/private/tls.key"`, servicePort, servicePort)
// Add SSLProtocol only if explicitly set
switch r.TLSMinVersion {
case "VersionTLS10":
httpdConfigBase += "\n\tSSLProtocol -all +TLSv1 +TLSv1.1 +TLSv1.2 +TLSv1.3"
case "VersionTLS11":
httpdConfigBase += "\n\tSSLProtocol -all +TLSv1.1 +TLSv1.2 +TLSv1.3"
case "VersionTLS12":
httpdConfigBase += "\n\tSSLProtocol -all +TLSv1.2 +TLSv1.3"
case "VersionTLS13":
httpdConfigBase += "\n\tSSLProtocol -all +TLSv1.3"
}
if TLSVersionToPlugin(r.TLSMinVersion) != "TLSv1.3" && strings.Join(r.TLSCiphers, ":") != "" {
httpdConfigBase += fmt.Sprintf("\n\tSSLCipherSuite %s", strings.Join(r.TLSCiphers, ":"))
Comment thread
akhilnittala marked this conversation as resolved.
}
// Close VirtualHost
httpdConfigBase += "\n</VirtualHost>"
return httpdConfigBase
}

// pluginConfigMap creates the ConfigMap with dynamic httpd.conf
func (r *ReconcileGitopsService) pluginConfigMap() *corev1.ConfigMap {
httpdConfig := r.buildHttpdConfig()

func pluginConfigMap() *corev1.ConfigMap {
cm := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: httpdConfigMapName,
Expand Down Expand Up @@ -337,7 +375,7 @@ func sortTolerations(tolerations []corev1.Toleration) []corev1.Toleration {
return sorted
}

func (r *ReconcileGitopsService) reconcileDeployment(cr *pipelinesv1alpha1.GitopsService, request reconcile.Request) (reconcile.Result, error) {
func (r *ReconcileGitopsService) reconcileDeployment(cr *pipelinesv1alpha1.GitopsService, request reconcile.Request, newPluginConfigMap *corev1.ConfigMap) (reconcile.Result, error) {
reqLogger := logs.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
newPluginDeployment := pluginDeployment(cr.Spec.ImagePullPolicy)

Expand All @@ -359,6 +397,13 @@ func (r *ReconcileGitopsService) reconcileDeployment(cr *pipelinesv1alpha1.Gitop
newPluginDeployment.Spec.Template.Spec.Tolerations = cr.Spec.Tolerations
}

// ADD THIS: Get ConfigMap and add hash to pod template annotations
configMapHash := getConfigMapHash(newPluginConfigMap)
if newPluginDeployment.Spec.Template.ObjectMeta.Annotations == nil {
newPluginDeployment.Spec.Template.ObjectMeta.Annotations = make(map[string]string)
}
newPluginDeployment.Spec.Template.ObjectMeta.Annotations["httpd-cfg-hash"] = configMapHash

// Check if this Deployment already exists
existingPluginDeployment := &appsv1.Deployment{}

Expand All @@ -381,6 +426,7 @@ func (r *ReconcileGitopsService) reconcileDeployment(cr *pipelinesv1alpha1.Gitop
!equality.Semantic.DeepEqual(existingPluginDeployment.Spec.Replicas, newPluginDeployment.Spec.Replicas) ||
!equality.Semantic.DeepEqual(existingPluginDeployment.Spec.Selector, newPluginDeployment.Spec.Selector) ||
!equality.Semantic.DeepEqual(existingSpecTemplate.Labels, newSpecTemplate.Labels) ||
!equality.Semantic.DeepEqual(existingSpecTemplate.ObjectMeta.Annotations["httpd-cfg-hash"], newSpecTemplate.ObjectMeta.Annotations["httpd-cfg-hash"]) ||
!equality.Semantic.DeepEqual(sortContainers(existingSpecTemplate.Spec.Containers), sortContainers(newSpecTemplate.Spec.Containers)) ||
!equality.Semantic.DeepEqual(sortVolumes(existingSpecTemplate.Spec.Volumes), sortVolumes(newSpecTemplate.Spec.Volumes)) ||
!equality.Semantic.DeepEqual(existingSpecTemplate.Spec.RestartPolicy, newSpecTemplate.Spec.RestartPolicy) ||
Expand All @@ -391,11 +437,15 @@ func (r *ReconcileGitopsService) reconcileDeployment(cr *pipelinesv1alpha1.Gitop
!equality.Semantic.DeepEqual(existingSpecTemplate.Spec.Containers[0].Resources, newSpecTemplate.Spec.Containers[0].Resources)

if changed {
if existingSpecTemplate.ObjectMeta.Annotations == nil {
existingSpecTemplate.ObjectMeta.Annotations = make(map[string]string)
}
reqLogger.Info("Reconciling plugin deployment", "Namespace", existingPluginDeployment.Namespace, "Name", existingPluginDeployment.Name)
existingPluginDeployment.Labels = newPluginDeployment.Labels
existingPluginDeployment.Spec.Replicas = newPluginDeployment.Spec.Replicas
existingPluginDeployment.Spec.Selector = newPluginDeployment.Spec.Selector
existingSpecTemplate.Labels = newSpecTemplate.Labels
existingSpecTemplate.ObjectMeta.Annotations["httpd-cfg-hash"] = newSpecTemplate.ObjectMeta.Annotations["httpd-cfg-hash"]
Comment thread
akhilnittala marked this conversation as resolved.
existingSpecTemplate.Spec.SecurityContext = newSpecTemplate.Spec.SecurityContext
existingSpecTemplate.Spec.Containers = newSpecTemplate.Spec.Containers
existingSpecTemplate.Spec.Volumes = newSpecTemplate.Spec.Volumes
Expand Down Expand Up @@ -487,9 +537,27 @@ func (r *ReconcileGitopsService) reconcileConsolePlugin(instance *pipelinesv1alp
return reconcile.Result{}, nil
}

func (r *ReconcileGitopsService) reconcileConfigMap(instance *pipelinesv1alpha1.GitopsService, request reconcile.Request) (reconcile.Result, error) {
// getConfigMapHash returns a deterministic SHA256 hash of ConfigMap data for change detection.
func getConfigMapHash(cm *corev1.ConfigMap) string {
hash := sha256.New()
keys := make([]string, 0, len(cm.Data))
for key := range cm.Data {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
if _, err := io.WriteString(hash, key); err != nil {
panic(fmt.Sprintf("failed to hash configmap key: %v", err))
}
if _, err := io.WriteString(hash, cm.Data[key]); err != nil {
panic(fmt.Sprintf("failed to hash configmap value: %v", err))
}
}
return hex.EncodeToString(hash.Sum(nil))
}

func (r *ReconcileGitopsService) reconcileConfigMap(instance *pipelinesv1alpha1.GitopsService, request reconcile.Request, newPluginConfigMap *corev1.ConfigMap) (reconcile.Result, error) {
reqLogger := logs.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
newPluginConfigMap := pluginConfigMap()

if err := controllerutil.SetControllerReference(instance, newPluginConfigMap, r.Scheme); err != nil {
return reconcile.Result{}, err
Expand All @@ -515,7 +583,7 @@ func (r *ReconcileGitopsService) reconcileConfigMap(instance *pipelinesv1alpha1.
reqLogger.Info("Reconciling plugin configMap", "Namespace", existingPluginConfigMap.Namespace, "Name", existingPluginConfigMap.Name)
existingPluginConfigMap.Data = newPluginConfigMap.Data
existingPluginConfigMap.Labels = newPluginConfigMap.Labels
return reconcile.Result{}, r.Client.Update(context.TODO(), newPluginConfigMap)
return reconcile.Result{}, r.Client.Update(context.TODO(), existingPluginConfigMap)
}
}
return reconcile.Result{}, nil
Expand All @@ -529,15 +597,18 @@ func (r *ReconcileGitopsService) reconcilePlugin(instance *pipelinesv1alpha1.Git
return reconcile.Result{}, nil
}

// Generate ConfigMap once
newPluginConfigMap := r.pluginConfigMap()

if result, err := r.reconcileService(instance, request); err != nil {
return result, err
}

if result, err := r.reconcileDeployment(instance, request); err != nil {
if result, err := r.reconcileConfigMap(instance, request, newPluginConfigMap); err != nil {
return result, err
}

if result, err := r.reconcileConfigMap(instance, request); err != nil {
if result, err := r.reconcileDeployment(instance, request, newPluginConfigMap); err != nil {
return result, err
}

Expand Down
Loading
Loading