Skip to content

Commit

Permalink
Migrate all secrets in reconcile migration
Browse files Browse the repository at this point in the history
Signed-off-by: Mykola Morhun <mmorhun@redhat.com>
  • Loading branch information
mmorhun committed Nov 11, 2021
1 parent d1e1a75 commit 0855e4d
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 56 deletions.
2 changes: 1 addition & 1 deletion controllers/che/checluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ func NewReconciler(
reconcileManager := deploy.NewReconcileManager()

// order does matter
reconcileManager.RegisterReconciler(migration.NewMigrator())
if !util.IsTestMode() {
reconcileManager.RegisterReconciler(migration.NewMigrator())
reconcileManager.RegisterReconciler(NewCheClusterValidator())
}
reconcileManager.RegisterReconciler(imagepuller.NewImagePuller())
Expand Down
134 changes: 115 additions & 19 deletions pkg/deploy/migration/on-reconcile-one-time-migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import (
"time"

"github.com/eclipse-che/che-operator/pkg/deploy"
corev1 "k8s.io/api/core/v1"
"github.com/eclipse-che/che-operator/pkg/util"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

Expand All @@ -44,9 +45,7 @@ func (m *Migrator) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool,
}

result, done, err := m.migrate(ctx)
if done && err == nil {
m.migrationDone = true
}
m.migrationDone = done && err == nil
return result, done, err
}

Expand All @@ -55,41 +54,138 @@ func (m *Migrator) Finalize(ctx *deploy.DeployContext) error {
}

func (m *Migrator) migrate(ctx *deploy.DeployContext) (reconcile.Result, bool, error) {
// Add required labels for the config map with additional CA certificates
if err := addRequiredLabelsForConfigMaps(ctx); err != nil {
return reconcile.Result{}, false, err
}

if err := addRequiredLabelsForSecrets(ctx); err != nil {
return reconcile.Result{}, false, err
}

// Give some time for the migration resources to be flushed
return reconcile.Result{RequeueAfter: 5 * time.Second}, true, nil
}

// addRequiredLabelsForConfigMaps processes the following cofig maps:
// - 'che-git-self-signed-cert' if spec.server.gitSelfSignedCert is set to true
// - spec.server.serverTrustStoreConfigMapName (legacy way to add trusted CA certificates)
func addRequiredLabelsForConfigMaps(ctx *deploy.DeployContext) error {
// Legacy config map with additional CA certificates
if ctx.CheCluster.Spec.Server.ServerTrustStoreConfigMapName != "" {
if err := addRequiredLabelsForConfigMap(ctx, ctx.CheCluster.Spec.Server.ServerTrustStoreConfigMapName, deploy.CheCACertsConfigMapLabelValue); err != nil {
return reconcile.Result{}, false, err
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Server.ServerTrustStoreConfigMapName, deploy.CheCACertsConfigMapLabelValue); err != nil {
return err
}
}

// Add required labels for the config map with CA certificates for git
// Config map with CA certificates for git
if ctx.CheCluster.Spec.Server.GitSelfSignedCert {
if err := addRequiredLabelsForConfigMap(ctx, gitSelfSignedCertsConfigMapName, deploy.CheCACertsConfigMapLabelValue); err != nil {
return reconcile.Result{}, false, err
if err := addRequiredLabelsForObject(ctx, gitSelfSignedCertsConfigMapName, deploy.CheCACertsConfigMapLabelValue); err != nil {
return err
}
}

// Give some time for the migration resources to be flushed
return reconcile.Result{RequeueAfter: 5 * time.Second}, true, nil
return nil
}

// addRequiredLabelsForSecrets processes the following secrets:
// - spec.k8s.tlsSecretName
// - 'self-signed-certificate' secret
// - spec.server.cheHostTLSSecret
// - spec.server.proxySecret
// - spec.database.chePostgresSecret
// - spec.auth.identityProviderSecret
// - spec.auth.identityProviderPostgresSecret
// - spec.auth.oAuthSecret
// Note, most of the secrets above are autogenerated and do not require any migraation,
// but to handle the case when some were created manually, the check is done here.
func addRequiredLabelsForSecrets(ctx *deploy.DeployContext) error {
if !util.IsOpenShift {
// Kubernetes only

tlsSecretName := "che-tls"
if ctx.CheCluster.Spec.K8s.TlsSecretName != "" {
tlsSecretName = ctx.CheCluster.Spec.K8s.TlsSecretName
}
if err := addRequiredLabelsForObject(ctx, tlsSecretName, cheFlavor); err != nil {
return err
}
}

// TLS
if err := addRequiredLabelsForObject(ctx, deploy.CheTLSSelfSignedCertificateSecretName, cheFlavor); err != nil {
return err
}

if ctx.CheCluster.Spec.Server.CheHostTLSSecret != "" {
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Server.CheHostTLSSecret, cheFlavor); err != nil {
return err
}
}

// Proxy credentials
if ctx.CheCluster.Spec.Server.ProxySecret != "" {
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Server.ProxySecret, cheFlavor); err != nil {
return err
}
}

// Database credentials
if ctx.CheCluster.Spec.Database.ChePostgresSecret != "" {
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Database.ChePostgresSecret, cheFlavor); err != nil {
return err
}
}

// Keycloak related secrets
if ctx.CheCluster.Spec.Auth.IdentityProviderSecret != "" {
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Auth.IdentityProviderSecret, cheFlavor); err != nil {
return err
}
}

if ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret != "" {
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Auth.IdentityProviderPostgresSecret, cheFlavor); err != nil {
return err
}
}

// OAuth
if ctx.CheCluster.Spec.Auth.OAuthSecret != "" {
if err := addRequiredLabelsForObject(ctx, ctx.CheCluster.Spec.Auth.OAuthSecret, cheFlavor); err != nil {
return err
}
}

return nil
}

func addRequiredLabelsForConfigMap(ctx *deploy.DeployContext, configMapName string, componentName string) error {
configMap := &corev1.ConfigMap{}
err := ctx.ClusterAPI.NonCachingClient.Get(context.TODO(), types.NamespacedName{Namespace: ctx.CheCluster.Namespace, Name: configMapName}, configMap)
func addRequiredLabelsForObject(ctx *deploy.DeployContext, objectName string, componentName string) error {
// Check if the object is already migrated
var obj client.Object
if exists, _ := deploy.GetNamespacedObject(ctx, objectName, obj); exists {
// Default client sees the object in cache, no need in adding labels
return nil
}

err := ctx.ClusterAPI.NonCachingClient.Get(context.TODO(), types.NamespacedName{Namespace: ctx.CheCluster.Namespace, Name: objectName}, obj)
if err != nil {
if errors.IsNotFound(err) {
// The object doesn't exist in cluster, nothing to do
return nil
}
return err
}

if configMap.ObjectMeta.Labels == nil {
configMap.ObjectMeta.Labels = make(map[string]string)
// Add required labels to the object
labels := obj.GetLabels()
if labels == nil {
labels = make(map[string]string)
}
for labelName, labelValue := range deploy.GetLabels(ctx.CheCluster, componentName) {
configMap.ObjectMeta.Labels[labelName] = labelValue
labels[labelName] = labelValue
}
if err := ctx.ClusterAPI.NonCachingClient.Update(context.TODO(), configMap); err != nil {
obj.SetLabels(labels)
if err := ctx.ClusterAPI.NonCachingClient.Update(context.TODO(), obj); err != nil {
return err
}

Expand Down
37 changes: 1 addition & 36 deletions pkg/deploy/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,6 @@ func K8sHandleCheTLSSecrets(deployContext *DeployContext) (reconcile.Result, err
return reconcile.Result{RequeueAfter: time.Second}, err
}

requiredLabels := GetLabels(deployContext.CheCluster, cheTLSSecretName)

// Check if a job is already running for TLS secrets creation
if jobExists {
if job.Status.Succeeded == 0 && job.Status.Failed == 0 {
Expand All @@ -339,39 +337,6 @@ func K8sHandleCheTLSSecrets(deployContext *DeployContext) (reconcile.Result, err
// Secrets are ready, restart reconcilation loop
return reconcile.Result{}, nil
}
} else {
// Handle case when the secret(s) exists, but miss the required labels
err = deployContext.ClusterAPI.NonCachingClient.Get(context.TODO(), cheTLSSecretNamespacedName, cheTLSSecret)
if err == nil {
// Che TLS secret exists, add required labels
addLabelsToSecret(requiredLabels, cheTLSSecret)
err := deployContext.ClusterAPI.NonCachingClient.Update(context.TODO(), cheTLSSecret)
if err == nil {
// Try to do the same for CA certifaicete if any
cheTLSSelfSignedCertificateSecret := &corev1.Secret{}
err = deployContext.ClusterAPI.NonCachingClient.Get(context.TODO(), CheTLSSelfSignedCertificateSecretNamespacedName, cheTLSSelfSignedCertificateSecret)
if err == nil {
// CA certifaicete secret exists, add required labels
addLabelsToSecret(requiredLabels, cheTLSSelfSignedCertificateSecret)
err = deployContext.ClusterAPI.NonCachingClient.Update(context.TODO(), cheTLSSelfSignedCertificateSecret)
return reconcile.Result{RequeueAfter: time.Second}, err
} else if !errors.IsNotFound(err) {
// Error reading CA certificate secret
logrus.Errorf("Error getting Che self-signed certificate secert \"%s\": %v", CheTLSSelfSignedCertificateSecretName, err)
return reconcile.Result{RequeueAfter: time.Second}, err
}
// Che self-signed CA certificate secert doesn't exists.
// Consider, that a commonly trusted TLS certificate is used.
return reconcile.Result{}, nil
} else {
// Failed to update Che TLS secret with the required labels
return reconcile.Result{RequeueAfter: time.Second}, err
}
} else if !errors.IsNotFound(err) {
// Error reading Che TLS secret info
logrus.Errorf("Error getting Che TLS secert \"%s\": %v", cheTLSSecretName, err)
return reconcile.Result{RequeueAfter: time.Second}, err
}
}

// Che TLS secret doesn't exist, generate a new one
Expand Down Expand Up @@ -416,7 +381,7 @@ func K8sHandleCheTLSSecrets(deployContext *DeployContext) (reconcile.Result, err
}

labels := ""
for labelName, labelValue := range requiredLabels {
for labelName, labelValue := range GetLabels(deployContext.CheCluster, cheTLSSecretName) {
labels += fmt.Sprintf("%s=%s ", labelName, labelValue)
}

Expand Down

0 comments on commit 0855e4d

Please sign in to comment.