thelabdude commented on a change in pull request #151:
URL: 
https://github.com/apache/lucene-solr-operator/pull/151#discussion_r568133031



##########
File path: controllers/solrcloud_controller.go
##########
@@ -772,3 +848,188 @@ func (r *SolrCloudReconciler) 
indexAndWatchForProvidedConfigMaps(mgr ctrl.Manage
                },
                
builder.WithPredicates(predicate.ResourceVersionChangedPredicate{})), nil
 }
+
+// Reconciles the TLS cert, returns either a bool to indicate if the cert is 
ready or an error
+func (r *SolrCloudReconciler) reconcileAutoCreateTLS(ctx context.Context, 
instance *solr.SolrCloud) (bool, error) {
+
+       // short circuit this method with a quick check if the cert exists and 
is ready
+       // this is useful b/c it may take many minutes for a cert to be issued, 
so we avoid
+       // all the other checking that happens below while we're waiting for 
the cert
+       foundCert := &certv1.Certificate{}
+       if err := r.Get(ctx, types.NamespacedName{Name: 
instance.Spec.SolrTLS.AutoCreate.Name, Namespace: instance.Namespace}, 
foundCert); err == nil {
+               // cert exists, but is it ready? need to wait until we see the 
TLS secret
+               if foundTLSSecret := r.isCertificateReady(ctx, foundCert, 
instance.Spec.SolrTLS); foundTLSSecret != nil {
+                       cert := util.GenerateCertificate(instance)
+                       return r.afterCertificateReady(ctx, instance, &cert, 
foundCert, foundTLSSecret)
+               }
+       }
+
+       r.Log.Info("Reconciling TLS config", "tls", instance.Spec.SolrTLS)
+
+       // cert not found, do full reconcile for TLS ...
+       var err error
+       var tlsReady bool
+
+       // First, create the keystore password secret if needed
+       keystoreSecret := util.GenerateKeystoreSecret(instance)
+       foundSecret := &corev1.Secret{}
+       err = r.Get(ctx, types.NamespacedName{Name: keystoreSecret.Name, 
Namespace: keystoreSecret.Namespace}, foundSecret)
+       if err != nil && errors.IsNotFound(err) {
+               r.Log.Info("Creating keystore secret", "namespace", 
keystoreSecret.Namespace, "name", keystoreSecret.Name)
+               if err := controllerutil.SetControllerReference(instance, 
&keystoreSecret, r.scheme); err != nil {
+                       return false, err
+               }
+               err = r.Create(ctx, &keystoreSecret)
+       }
+       if err != nil {
+               return false, err
+       }
+
+       // Create a self-signed cert issuer if no issuerRef provided
+       if instance.Spec.SolrTLS.AutoCreate.IssuerRef == nil {
+               issuerName := fmt.Sprintf("%s-selfsigned-issuer", instance.Name)
+               foundIssuer := &certv1.Issuer{}
+               err = r.Get(ctx, types.NamespacedName{Name: issuerName, 
Namespace: instance.Namespace}, foundIssuer)
+               if err != nil && errors.IsNotFound(err) {
+                       // specified Issuer not found, let's go create a 
self-signed for this
+                       issuer := util.GenerateSelfSignedIssuer(instance, 
issuerName)
+                       if err := 
controllerutil.SetControllerReference(instance, &issuer, r.scheme); err != nil {
+                               return false, err
+                       }
+                       r.Log.Info("Creating Self-signed Certificate Issuer", 
"issuer", issuer)
+                       err = r.Create(ctx, &issuer)
+               } else if err == nil {
+                       r.Log.Info("Found Self-signed Certificate Issuer", 
"issuer", issuerName)
+               }
+               if err != nil {
+                       return false, err
+               }
+       } else {
+               // real problems arise if we create the Certificate and the 
Issuer doesn't exist so make we have a good config here
+               if instance.Spec.SolrTLS.AutoCreate.IssuerRef.Kind == "Issuer" {
+                       foundIssuer := &certv1.Issuer{}
+                       err = r.Get(ctx, types.NamespacedName{Name: 
instance.Spec.SolrTLS.AutoCreate.IssuerRef.Name, Namespace: 
instance.Namespace}, foundIssuer)
+                       if err != nil {
+                               if errors.IsNotFound(err) {
+                                       r.Log.Info("cert-manager Issuer not 
found in namespace, cannot create a TLS certificate without an Issuer",
+                                               "issuer", 
instance.Spec.SolrTLS.AutoCreate.IssuerRef.Name, "ns", instance.Namespace)
+                               }
+                               return false, err
+                       }
+               } // else assume ClusterIssuer and good luck
+       }
+
+       // Reconcile the Certificate to use for TLS ... A Certificate is a 
request to Issue the cert, the
+       // actual cert lives in a TLS secret created by the Issuer
+       cert := util.GenerateCertificate(instance)
+       err = r.Get(ctx, types.NamespacedName{Name: cert.Name, Namespace: 
cert.Namespace}, foundCert)
+       if err != nil && errors.IsNotFound(err) {
+               r.Log.Info("Creating Certificate", "cert", cert)
+               // Set the operator as the owner of the cert
+               if err := controllerutil.SetControllerReference(instance, 
&cert, r.scheme); err != nil {
+                       return false, err
+               }
+               // Create the cert
+               err = r.Create(ctx, &cert)
+               if err != nil {
+                       return false, err
+               }
+       } else if err == nil {
+               r.Log.Info("Found Certificate, checking if it is ready", 
"cert", foundCert.Name)
+               if foundTLSSecret := r.isCertificateReady(ctx, foundCert, 
instance.Spec.SolrTLS); foundTLSSecret != nil {
+                       tlsReady, err = r.afterCertificateReady(ctx, instance, 
&cert, foundCert, foundTLSSecret)
+                       if tlsReady {
+                               r.Log.Info("TLS Certificate reconciled.", 
"cert", foundCert.Name)
+                       }
+               } else {
+                       r.Log.Info("Certificate not ready, current status", 
"status", foundCert.Status)
+               }
+       }
+
+       if err != nil {
+               return false, err
+       }
+
+       return tlsReady, nil
+}
+
+func (r *SolrCloudReconciler) isCertificateReady(ctx context.Context, cert 
*certv1.Certificate, tlsOpts *solr.SolrTLSOptions) *corev1.Secret {
+       // Cert is ready, lookup the secret holding the keystore
+       foundTLSSecret := &corev1.Secret{}
+       err := r.Get(ctx, types.NamespacedName{Name: cert.Spec.SecretName, 
Namespace: cert.Namespace}, foundTLSSecret)
+       if err != nil {
+               if errors.IsNotFound(err) {
+                       r.Log.Info("TLS secret not found", "name", 
cert.Spec.SecretName)
+               } else {
+                       r.Log.Error(err, "TLS secret lookup failed", "name", 
cert.Spec.SecretName)
+               }
+               foundTLSSecret = nil
+       }
+
+       if foundTLSSecret == nil {
+               if cert.Status.Conditions != nil {
+                       for _, cond := range cert.Status.Conditions {
+                               if cond.Type == 
certv1.CertificateConditionIssuing {
+                                       r.Log.Info("Certificate is still 
issuing", "name", cert.Name, "status", cond.Status)

Review comment:
       Most likely the user will need to look at the cert-manager logs to 
figure out why the cert is not issuing as there isn't much info in the 
Status.Conditions that I've seen.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@lucene.apache.org
For additional commands, e-mail: issues-h...@lucene.apache.org

Reply via email to