From 47a01d7276c8422d3eea61de0aba5bee017fbe2a Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Tue, 13 Oct 2020 14:04:20 +0300 Subject: [PATCH] Automatically propagate ca-certs configmap content into server and identity provider (#487) * Automatically propagate serverTrustStoreConfigMap context to server and identity provider Signed-off-by: Anatolii Bazko --- pkg/controller/che/che_controller.go | 86 +++++++++++++------ pkg/controller/che/get.go | 12 --- .../identity-provider/deployment_keycloak.go | 15 +++- .../identity-provider/identity_provider.go | 8 +- pkg/deploy/server/che_configmap.go | 8 ++ pkg/deploy/server/configmap_cert.go | 12 +++ pkg/deploy/server/deployment_che.go | 11 ++- 7 files changed, 108 insertions(+), 44 deletions(-) diff --git a/pkg/controller/che/che_controller.go b/pkg/controller/che/che_controller.go index 991112054..e7cee08a3 100644 --- a/pkg/controller/che/che_controller.go +++ b/pkg/controller/che/che_controller.go @@ -14,17 +14,17 @@ package che import ( "context" "fmt" - "github.com/eclipse/che-operator/pkg/deploy/devfile-registry" - "github.com/eclipse/che-operator/pkg/deploy/gateway" - "github.com/eclipse/che-operator/pkg/deploy/identity-provider" - "github.com/eclipse/che-operator/pkg/deploy/plugin-registry" - "github.com/eclipse/che-operator/pkg/deploy/postgres" - "github.com/eclipse/che-operator/pkg/deploy/server" "strconv" "time" orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1" "github.com/eclipse/che-operator/pkg/deploy" + devfile_registry "github.com/eclipse/che-operator/pkg/deploy/devfile-registry" + "github.com/eclipse/che-operator/pkg/deploy/gateway" + identity_provider "github.com/eclipse/che-operator/pkg/deploy/identity-provider" + plugin_registry "github.com/eclipse/che-operator/pkg/deploy/plugin-registry" + "github.com/eclipse/che-operator/pkg/deploy/postgres" + "github.com/eclipse/che-operator/pkg/deploy/server" "github.com/eclipse/che-operator/pkg/util" configv1 "github.com/openshift/api/config/v1" oauthv1 "github.com/openshift/api/config/v1" @@ -43,9 +43,10 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" logf "sigs.k8s.io/controller-runtime/pkg/runtime/log" "sigs.k8s.io/controller-runtime/pkg/source" @@ -80,6 +81,21 @@ func newReconciler(mgr manager.Manager) (reconcile.Reconciler, error) { func add(mgr manager.Manager, r reconcile.Reconciler) error { isOpenShift, _, err := util.DetectOpenShift() + onAllExceptGenericEventsPredicate := predicate.Funcs{ + UpdateFunc: func(evt event.UpdateEvent) bool { + return true + }, + CreateFunc: func(evt event.CreateEvent) bool { + return true + }, + DeleteFunc: func(evt event.DeleteEvent) bool { + return true + }, + GenericFunc: func(evt event.GenericEvent) bool { + return false + }, + } + if err != nil { logrus.Errorf("An error occurred when detecting current infra: %s", err) } @@ -150,6 +166,20 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { return err } + var toRequestMapper handler.ToRequestsFunc = func(obj handler.MapObject) []reconcile.Request { + isTrusted, reconcileRequest := isTrustedBundleConfigMap(mgr, obj) + if isTrusted { + return []reconcile.Request{reconcileRequest} + } + return []reconcile.Request{} + } + err = c.Watch(&source.Kind{Type: &corev1.ConfigMap{}}, &handler.EnqueueRequestsFromMapFunc{ + ToRequests: toRequestMapper, + }, onAllExceptGenericEventsPredicate) + if err != nil { + return err + } + err = c.Watch(&source.Kind{Type: &rbac.Role{}}, &handler.EnqueueRequestForOwner{ IsController: true, OwnerType: &orgv1.CheCluster{}, @@ -772,7 +802,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } // create and provision Keycloak related objects - provisioned, err := identity_provider.SyncIdentityProviderToCluster(deployContext, cheHost, protocol, cheFlavor) + provisioned, err := identity_provider.SyncIdentityProviderToCluster(deployContext) if !tests { if !provisioned { if err != nil { @@ -802,13 +832,6 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } } - if serverTrustStoreConfigMapName := instance.Spec.Server.ServerTrustStoreConfigMapName; serverTrustStoreConfigMapName != "" { - certMap := r.GetEffectiveConfigMap(instance, serverTrustStoreConfigMapName) - if err := controllerutil.SetControllerReference(instance, certMap, r.scheme); err != nil { - logrus.Errorf("An error occurred: %s", err) - } - } - // create Che ConfigMap which is synced with CR and is not supposed to be manually edited // controller will reconcile this CM with CR spec cheConfigMap, err := server.SyncCheConfigMapToCluster(deployContext) @@ -822,15 +845,6 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } } - // configMap resource version will be an env in Che deployment to easily update it when a ConfigMap changes - // which will automatically trigger Che rolling update - var cmResourceVersion string - if tests { - cmResourceVersion = r.GetEffectiveConfigMap(instance, server.CheConfigMapName).ResourceVersion - } else { - cmResourceVersion = cheConfigMap.ResourceVersion - } - err = gateway.SyncGatewayToCluster(deployContext) if err != nil { logrus.Errorf("Failed to create the Server Gateway: %s", err) @@ -838,7 +852,7 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } // Create a new che deployment - deploymentStatus := server.SyncCheDeploymentToCluster(deployContext, cmResourceVersion) + deploymentStatus := server.SyncCheDeploymentToCluster(deployContext) if !tests { if !deploymentStatus.Continue { logrus.Infof("Waiting on deployment '%s' to be ready", cheFlavor) @@ -1017,3 +1031,25 @@ func getServerExposingServiceName(cr *orgv1.CheCluster) string { } return deploy.CheServiceName } + +func isTrustedBundleConfigMap(mgr manager.Manager, obj handler.MapObject) (bool, reconcile.Request) { + checlusters := &orgv1.CheClusterList{} + if err := mgr.GetClient().List(context.TODO(), &client.ListOptions{}, checlusters); err != nil { + return false, reconcile.Request{} + } + + if len(checlusters.Items) != 1 { + return false, reconcile.Request{} + } + + if checlusters.Items[0].Spec.Server.ServerTrustStoreConfigMapName != obj.Meta.GetName() { + return false, reconcile.Request{} + } + + return true, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Namespace: checlusters.Items[0].Namespace, + Name: checlusters.Items[0].Name, + }, + } +} diff --git a/pkg/controller/che/get.go b/pkg/controller/che/get.go index 5201fd5db..8097be7fd 100644 --- a/pkg/controller/che/get.go +++ b/pkg/controller/che/get.go @@ -18,7 +18,6 @@ import ( oauth "github.com/openshift/api/oauth/v1" "github.com/sirupsen/logrus" appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -29,17 +28,6 @@ func (r *ReconcileChe) GetEffectiveDeployment(instance *orgv1.CheCluster, name s return deployment, err } -func (r *ReconcileChe) GetEffectiveConfigMap(instance *orgv1.CheCluster, name string) (configMap *corev1.ConfigMap) { - configMap = &corev1.ConfigMap{} - err := r.client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: instance.Namespace}, configMap) - if err != nil { - logrus.Errorf("Failed to get %s config map: %s", name, err) - return nil - } - return configMap - -} - func (r *ReconcileChe) GetCR(request reconcile.Request) (instance *orgv1.CheCluster, err error) { instance = &orgv1.CheCluster{} err = r.client.Get(context.TODO(), request.NamespacedName, instance) diff --git a/pkg/deploy/identity-provider/deployment_keycloak.go b/pkg/deploy/identity-provider/deployment_keycloak.go index da9e11a09..08cbf0372 100644 --- a/pkg/deploy/identity-provider/deployment_keycloak.go +++ b/pkg/deploy/identity-provider/deployment_keycloak.go @@ -12,13 +12,15 @@ package identity_provider import ( + "github.com/eclipse/che-operator/pkg/deploy/server" "context" - "github.com/eclipse/che-operator/pkg/deploy" - "github.com/eclipse/che-operator/pkg/deploy/postgres" "regexp" "strconv" "strings" + "github.com/eclipse/che-operator/pkg/deploy" + "github.com/eclipse/che-operator/pkg/deploy/postgres" + orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1" "github.com/eclipse/che-operator/pkg/util" "github.com/google/go-cmp/cmp" @@ -101,6 +103,7 @@ func getSpecKeycloakDeployment( } } + cmResourceVersions := server.GetTrustStoreConfigMapVersion(deployContext) terminationGracePeriodSeconds := int64(30) cheCertSecretVersion := getSecretResourceVersion("self-signed-certificate", deployContext.CheCluster.Namespace, deployContext.ClusterAPI) openshiftApiCertSecretVersion := getSecretResourceVersion("openshift-api-crt", deployContext.CheCluster.Namespace, deployContext.ClusterAPI) @@ -221,6 +224,10 @@ func getSpecKeycloakDeployment( } keycloakEnv := []corev1.EnvVar{ + { + Name: "CM_REVISION", + Value: cmResourceVersions, + }, { Name: "PROXY_ADDRESS_FORWARDING", Value: "true", @@ -348,6 +355,10 @@ func getSpecKeycloakDeployment( if cheFlavor == "codeready" { keycloakEnv = []corev1.EnvVar{ + { + Name: "CM_REVISION", + Value: cmResourceVersions, + }, { Name: "PROXY_ADDRESS_FORWARDING", Value: "true", diff --git a/pkg/deploy/identity-provider/identity_provider.go b/pkg/deploy/identity-provider/identity_provider.go index 8ff4686ae..aa0a7eb60 100644 --- a/pkg/deploy/identity-provider/identity_provider.go +++ b/pkg/deploy/identity-provider/identity_provider.go @@ -31,8 +31,14 @@ const ( // SyncIdentityProviderToCluster instantiates the identity provider (Keycloak) in the cluster. Returns true if // the provisioning is complete, false if requeue of the reconcile request is needed. -func SyncIdentityProviderToCluster(deployContext *deploy.DeployContext, cheHost string, protocol string, cheFlavor string) (bool, error) { +func SyncIdentityProviderToCluster(deployContext *deploy.DeployContext) (bool, error) { instance := deployContext.CheCluster + cheHost := instance.Spec.Server.CheHost + protocol := "http" + if instance.Spec.Server.TlsSupport { + protocol = "https" + } + cheFlavor := deploy.DefaultCheFlavor(instance) cheMultiUser := deploy.GetCheMultiUser(instance) tests := util.IsTestMode() isOpenShift := util.IsOpenShift diff --git a/pkg/deploy/server/che_configmap.go b/pkg/deploy/server/che_configmap.go index 53a9f57f8..e708884b1 100644 --- a/pkg/deploy/server/che_configmap.go +++ b/pkg/deploy/server/che_configmap.go @@ -271,3 +271,11 @@ func GetCheConfigMapData(deployContext *deploy.DeployContext) (cheEnv map[string addMap(cheEnv, deployContext.CheCluster.Spec.Server.CustomCheProperties) return cheEnv, nil } + +func GetCheConfigMapVersion(deployContext *deploy.DeployContext) string { + cheConfigMap, _ := deploy.GetClusterConfigMap("che", deployContext.CheCluster.Namespace, deployContext.ClusterAPI.Client) + if cheConfigMap != nil { + return cheConfigMap.ResourceVersion + } + return "" +} diff --git a/pkg/deploy/server/configmap_cert.go b/pkg/deploy/server/configmap_cert.go index c9d3f0b05..ab816fb0c 100644 --- a/pkg/deploy/server/configmap_cert.go +++ b/pkg/deploy/server/configmap_cert.go @@ -13,6 +13,7 @@ package server import ( "context" + "github.com/eclipse/che-operator/pkg/deploy" "github.com/sirupsen/logrus" @@ -53,3 +54,14 @@ func SyncTrustStoreConfigMapToCluster(deployContext *deploy.DeployContext) (*cor return clusterConfigMap, nil } + +func GetTrustStoreConfigMapVersion(deployContext *deploy.DeployContext) string { + if deployContext.CheCluster.Spec.Server.ServerTrustStoreConfigMapName != "" { + trustStoreConfigMap, _ := deploy.GetClusterConfigMap(deployContext.CheCluster.Spec.Server.ServerTrustStoreConfigMapName, deployContext.CheCluster.Namespace, deployContext.ClusterAPI.Client) + if trustStoreConfigMap != nil { + return trustStoreConfigMap.ResourceVersion + } + } + + return "" +} diff --git a/pkg/deploy/server/deployment_che.go b/pkg/deploy/server/deployment_che.go index 7ed4bcd44..2ad6c7317 100644 --- a/pkg/deploy/server/deployment_che.go +++ b/pkg/deploy/server/deployment_che.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) -func SyncCheDeploymentToCluster(deployContext *deploy.DeployContext, cmResourceVersion string) deploy.DeploymentProvisioningStatus { +func SyncCheDeploymentToCluster(deployContext *deploy.DeployContext) deploy.DeploymentProvisioningStatus { clusterDeployment, err := deploy.GetClusterDeployment(deploy.DefaultCheFlavor(deployContext.CheCluster), deployContext.CheCluster.Namespace, deployContext.ClusterAPI.Client) if err != nil { return deploy.DeploymentProvisioningStatus{ @@ -35,7 +35,7 @@ func SyncCheDeploymentToCluster(deployContext *deploy.DeployContext, cmResourceV } } - specDeployment, err := getSpecCheDeployment(deployContext, cmResourceVersion) + specDeployment, err := getSpecCheDeployment(deployContext) if err != nil { return deploy.DeploymentProvisioningStatus{ ProvisioningStatus: deploy.ProvisioningStatus{Err: err}, @@ -45,7 +45,7 @@ func SyncCheDeploymentToCluster(deployContext *deploy.DeployContext, cmResourceV return deploy.SyncDeploymentToCluster(deployContext, specDeployment, clusterDeployment, nil, nil) } -func getSpecCheDeployment(deployContext *deploy.DeployContext, cmResourceVersion string) (*appsv1.Deployment, error) { +func getSpecCheDeployment(deployContext *deploy.DeployContext) (*appsv1.Deployment, error) { isOpenShift, _, err := util.DetectOpenShift() if err != nil { return nil, err @@ -56,6 +56,9 @@ func getSpecCheDeployment(deployContext *deploy.DeployContext, cmResourceVersion return nil, err } + cmResourceVersions := GetCheConfigMapVersion(deployContext) + cmResourceVersions += "," + GetTrustStoreConfigMapVersion(deployContext) + terminationGracePeriodSeconds := int64(30) cheFlavor := deploy.DefaultCheFlavor(deployContext.CheCluster) labels := deploy.GetLabels(deployContext.CheCluster, cheFlavor) @@ -175,7 +178,7 @@ func getSpecCheDeployment(deployContext *deploy.DeployContext, cmResourceVersion cheEnv = append(cheEnv, corev1.EnvVar{ Name: "CM_REVISION", - Value: cmResourceVersion, + Value: cmResourceVersions, }, corev1.EnvVar{ Name: "KUBERNETES_NAMESPACE",